From c8641b1801c1935f7eef7c864f28e0ad18bcaa06 Mon Sep 17 00:00:00 2001 From: Sunny Patel Date: Thu, 9 Jul 2020 17:23:21 -0500 Subject: [PATCH] Add Document.path property with Tests. Closes #99 Update Tests to sync with Shields and Github caching. Fix Tests that couldn't fail. Update README and packages. --- .github/README.md | 41 ++++++++++++---- Document.ts | 4 ++ Tests.ts | 119 ++++++++++++++++++++++++++++++++++++---------- package-lock.json | 112 ++++++++++++++++++++++++------------------- package.json | 10 ++-- typings/Test.d.ts | 4 +- 6 files changed, 200 insertions(+), 90 deletions(-) diff --git a/.github/README.md b/.github/README.md index d0c658b..c588e2b 100644 --- a/.github/README.md +++ b/.github/README.md @@ -1,6 +1,6 @@ # Firestore for Google Apps Scripts -![GitHub release (latest by date)](https://img.shields.io/github/v/release/grahamearley/FirestoreGoogleAppsScript) +[![GitHub release (latest by date)](https://img.shields.io/github/v/release/grahamearley/FirestoreGoogleAppsScript)](/grahamearley/FirestoreGoogleAppsScript/releases/latest) [![Google Apps Script](https://img.shields.io/badge/google%20apps%20script-v8-%234285f4)](https://developers.google.com/apps-script/guides/v8-runtime) [![TypeScript](https://img.shields.io/badge/typescript-3.9.5-%23294E80)](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) [![clasp](https://img.shields.io/badge/built%20with-clasp-4285f4.svg)](/google/clasp) @@ -16,12 +16,11 @@ This library allows a user (or service account) to authenticate with Firestore a Read how this project was started [here](http://grahamearley.website/blog/2017/10/18/firestore-in-google-apps-script.html). -As of **v27**, this project has been updated to use the [GAS V8 runtime](https://developers.google.com/apps-script/guides/v8-runtime) with [Typescript](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html)! This introduces a number of [breaking changes](#breaking-changes). +As of **v27**, this project has been updated to use the [GAS V8 runtime](https://developers.google.com/apps-script/guides/v8-runtime) with [Typescript](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html)! This introduces a number of [breaking changes](#breaking-changes). Scripts utilizing the old Rhino runtime must use **v26**. ## Installation In the Google online script editor, select the `Resources` menu item and choose `Libraries...`. In the "Add a library" input box, enter **`1VUSl4b1r1eoNcRWotZM3e87ygkxvXltOgyDZhixqncz9lQ3MjfT1iKFw`** and click "Add." Choose the most recent version number. - ## Quick start #### Creating a service account The easiest way to use this library is to create a Google Service Account for your application and give it read/write access to your datastore. Giving a service account access to your datastore is like giving access to a user's account, but this account is strictly used by your script, not by a person. @@ -97,7 +96,6 @@ You can retrieve documents by calling the `getDocument` function: ```javascript const documentWithMetadata = firestore.getDocument("FirstCollection/FirstDocument"); -const storedObject = documentWithMetadata.obj; ``` You can also retrieve all documents within a collection by using the `getDocuments` function: @@ -112,6 +110,19 @@ You can also get specific documents by providing an array of document names const someDocuments = firestore.getDocuments("FirstCollection", ["Doc1", "Doc2", "Doc3"]); ``` +##### Getting Document Properties +You can access various properties of documents from Firestore: + +```javascript +const doc = firestore.getDocument("My Collection/My Document"); +const originalData = doc.obj // Original database object (your stored data) +const readTime = doc.read // Date Object of the Read time from database +const updateTime = doc.updated // Date Object of the Updated time from database +const createdTime = doc.created // Date Object of the Created time from database +const name = doc.name // Full document path (projects/projName/databases/(default)/documents/My Collection/My Document) +const path = doc.path // Local document path (My Collection/My Document) +``` + ##### Getting Documents (Advanced method using Query) If more specific queries need to be performed, you can use the `query` function followed by an `.Execute()` invocation to get that data: @@ -140,13 +151,23 @@ const documents3_4_5_6 = firestore.query("FirstCollection").Range(3, 7).Execute( See other library methods and details [in the wiki](/grahamearley/FirestoreGoogleAppsScript/wiki/). +### Frequently Asked Questions +- **I'm getting the following error:** + > Missing ; before statement. at \[unknown function\](Auth:12) + + This is because this library has been updated to utilize the new [V8 Engine](https://developers.google.com/apps-script/guides/v8-runtime), and classes are not supported in the Rhino Engine. + You can either: + 1. [Migrate your script to use V8](https://developers.google.com/apps-script/guides/v8-runtime/migration), or + 1. Use the last Rhino version of this library (**v26**). + + ### Breaking Changes -* **v27:** Library rewritten with Typescript and Prettier. - * Query function names have been capitalized (`Select`, `Where`, `OrderBy`, `Limit`, `Offset`, `Range`). - * **All functions return `Document` or `Document[]` types directly from Firebase. Use `document.obj` to extract the raw object.** - * Undo breaking change from v23. `document.createTime` and `document.updateTime` will remain as timestamped strings. However `document.created`, `document.updated`, and `document.read` are Date objects. -* **v23:** When retrieving documents the createTime and updateTime document properties are JS Date objects and not Timestamp Strings. -* **v16:** **Removed:** `createDocumentWithId(documentId, path, fields)` +- **v27:** Library rewritten with Typescript and Prettier. + - Query function names have been capitalized (`Select`, `Where`, `OrderBy`, `Limit`, `Offset`, `Range`). + - **All functions return `Document` or `Document[]` types directly from Firebase. Use `document.obj` to extract the raw object.** + - Undo breaking change from v23. `document.createTime` and `document.updateTime` will remain as timestamped strings. However `document.created`, `document.updated`, and `document.read` are Date objects. +- **v23:** When retrieving documents the createTime and updateTime document properties are JS Date objects and not Timestamp Strings. +- **v16:** **Removed:** `createDocumentWithId(documentId, path, fields)` > Utilize `createDocument(path + '/' + documentId, fields)` instead to create a document with a specific ID. ## Contributions diff --git a/Document.ts b/Document.ts index 0b26622..3fb7469 100644 --- a/Document.ts +++ b/Document.ts @@ -39,6 +39,10 @@ class Document implements FirestoreAPI.Document, FirestoreAPI.MapValue { return this.readTime ? Document.unwrapDate(this.readTime) : new Date(); } + get path() { + return this.name?.match(Util_.regexPath)![1]; + } + /** * Extract fields from a Firestore document. * diff --git a/Tests.ts b/Tests.ts index 93f282a..3fd96f5 100644 --- a/Tests.ts +++ b/Tests.ts @@ -13,12 +13,12 @@ function StoreCredentials_(): void { class Tests implements TestManager { db!: Firestore; pass: string[]; - fail: Record; + fail: Map; expected_!: Record; constructor(email: string, key: string, projectId: string, apiVersion: Version = 'v1', clearCollection = false) { this.pass = []; - this.fail = {}; + this.fail = new Map(); let funcs = Object.getOwnPropertyNames(Tests.prototype).filter( (property) => typeof (this as any)[property] === 'function' && property !== 'constructor' @@ -30,14 +30,11 @@ class Tests implements TestManager { this.pass.push('Test_Get_Firestore'); } catch (e) { // On failure, fail the remaining tests without execution - this.fail['Test_Get_Firestore'] = e; - const err: Error = { - name: 'Test Error', - message: 'Test Initialization Error', - stack: 'See Test_Get_Firestore Error', - }; + this.fail.set('Test_Get_Firestore', e); + const err = new Error('Test Initialization Error'); + err.stack = 'See Test_Get_Firestore Error'; for (const func of funcs) { - this.fail[func] = err; + this.fail.set(func, err); } return; } @@ -70,7 +67,13 @@ class Tests implements TestManager { (this as any)[func](); this.pass.push(func); } catch (e) { - this.fail[func] = typeof e === 'string' ? { message: 'AssertionError', stack: e } : e; + if (typeof e === 'string') { + const err = new Error('AssertionError'); + err.stack = e; + // eslint-disable-next-line no-ex-assign + e = err; + } + this.fail.set(func, e); } } } @@ -96,6 +99,7 @@ class Tests implements TestManager { const path = 'Test Collection/New Document'; const newDoc = this.db.createDocument(path); GSUnit.assertNotUndefined(newDoc); + GSUnit.assertEquals(path, newDoc.path); GSUnit.assertEquals(this.db.basePath + path, newDoc.name); GSUnit.assertNotUndefined(newDoc.createTime); GSUnit.assertNotUndefined(newDoc.updateTime); @@ -107,14 +111,17 @@ class Tests implements TestManager { try { this.db.createDocument(path); GSUnit.fail('Duplicate document without error'); - } catch (_e) { - /* db.createDocument should be throwing an error */ + } catch (e) { + if (e.message !== `Document already exists: ${this.db.basePath}${path}`) { + throw e; + } } } Test_Create_Document_Data(): void { const path = 'Test Collection/New Document !@#$%^&*(),.<>?;\':"[]{}|-=_+áéíóúæÆÑ'; const newDoc = this.db.createDocument(path, this.expected_); + GSUnit.assertEquals(path, newDoc.path); GSUnit.assertObjectEquals(this.expected_, newDoc.obj); } @@ -130,6 +137,7 @@ class Tests implements TestManager { 'null value': 'Not a Null', }; const updatedDoc = this.db.updateDocument(path, expected); + GSUnit.assertEquals(path, updatedDoc.path); GSUnit.assertObjectEquals(expected, updatedDoc.obj); } @@ -142,6 +150,7 @@ class Tests implements TestManager { this.db.createDocument(path, original); const expected = { 'number value': 42 }; const updatedDoc = this.db.updateDocument(path, expected, false); + GSUnit.assertEquals(path, updatedDoc.path); GSUnit.assertObjectEquals(expected, updatedDoc.obj); } @@ -155,6 +164,7 @@ class Tests implements TestManager { const updater = { 'string value 이': 'The new wave `~' }; const updatedDoc = this.db.updateDocument(path, updater, true); Object.assign(expected, updater); + GSUnit.assertEquals(path, updatedDoc.path); GSUnit.assertObjectEquals(expected, updatedDoc.obj); } @@ -162,6 +172,7 @@ class Tests implements TestManager { const path = 'Test Collection/Missing Document Overwrite'; const expected = { 'boolean value': false }; const updatedDoc = this.db.updateDocument(path, expected, false); + GSUnit.assertEquals(path, updatedDoc.path); GSUnit.assertObjectEquals(expected, updatedDoc.obj); } @@ -169,12 +180,14 @@ class Tests implements TestManager { const path = 'Test Collection/Missing Document Mask'; const expected = { 'boolean value': true }; const updatedDoc = this.db.updateDocument(path, expected, true); + GSUnit.assertEquals(path, updatedDoc.path); GSUnit.assertObjectEquals(expected, updatedDoc.obj); } Test_Get_Document(): void { const path = 'Test Collection/New Document !@#$%^&*(),.<>?;\':"[]{}|-=_+áéíóúæÆÑ'; const doc = this.db.getDocument(path); + GSUnit.assertEquals(path, doc.path); GSUnit.assertObjectEquals(this.expected_, doc.obj); } @@ -183,8 +196,10 @@ class Tests implements TestManager { try { this.db.getDocument(path); GSUnit.fail('Missing document without error'); - } catch (_e) { - /* db.getDocument should be throwing an error */ + } catch (e) { + if (e.message !== `Document "${this.db.basePath}${path}" not found.`) { + throw e; + } } } @@ -238,12 +253,8 @@ class Tests implements TestManager { Test_Get_Document_IDs_Missing(): void { const path = 'Missing Collection'; - try { - this.db.getDocumentIds(path); - GSUnit.fail('Missing collection without error'); - } catch (_e) { - /* db.getDocumentIds should be throwing an error */ - } + const docs = this.db.getDocumentIds(path); + GSUnit.assertEquals(0, docs.length); } Test_Query_All(): void { @@ -278,63 +289,113 @@ class Tests implements TestManager { } Test_Query_Where_EqEq_String(): void { + const expected = ['New Document !@#$%^&*(),.<>?;\':"[]{}|-=_+áéíóúæÆÑ']; const path = 'Test Collection'; const docs = this.db.query(path).Where('string value 이', '==', 'The fox jumps over the lazy dog 름').Execute(); GSUnit.assertEquals(1, docs.length); + GSUnit.assertArrayEqualsIgnoringOrder( + expected.map((p) => `${path}/${p}`), + docs.map((doc) => doc.path) + ); } Test_Query_Where_EqEqEq_String(): void { + const expected = ['New Document !@#$%^&*(),.<>?;\':"[]{}|-=_+áéíóúæÆÑ']; const path = 'Test Collection'; const docs = this.db.query(path).Where('string value 이', '===', 'The fox jumps over the lazy dog 름').Execute(); GSUnit.assertEquals(1, docs.length); + GSUnit.assertArrayEqualsIgnoringOrder( + expected.map((p) => `${path}/${p}`), + docs.map((doc) => doc.path) + ); } Test_Query_Where_Eq_Number(): void { + const expected = ['New Document !@#$%^&*(),.<>?;\':"[]{}|-=_+áéíóúæÆÑ']; const path = 'Test Collection'; const docs = this.db.query(path).Where('number value', '==', 100).Execute(); GSUnit.assertEquals(1, docs.length); + GSUnit.assertArrayEqualsIgnoringOrder( + expected.map((p) => `${path}/${p}`), + docs.map((doc) => doc.path) + ); } Test_Query_Where_Lt_Number(): void { + const expected = ['Updatable Document Overwrite']; const path = 'Test Collection'; const docs = this.db.query(path).Where('number value', '<', 100).Execute(); GSUnit.assertEquals(1, docs.length); + GSUnit.assertArrayEqualsIgnoringOrder( + expected.map((p) => `${path}/${p}`), + docs.map((doc) => doc.path) + ); } Test_Query_Where_Lte_Number(): void { + const expected = ['New Document !@#$%^&*(),.<>?;\':"[]{}|-=_+áéíóúæÆÑ', 'Updatable Document Overwrite']; const path = 'Test Collection'; const docs = this.db.query(path).Where('number value', '<=', 100).Execute(); GSUnit.assertEquals(2, docs.length); + GSUnit.assertArrayEqualsIgnoringOrder( + expected.map((p) => `${path}/${p}`), + docs.map((doc) => doc.path) + ); } Test_Query_Where_Gt_Number(): void { + const expected = ['Updatable Document Mask']; const path = 'Test Collection'; const docs = this.db.query(path).Where('number value', '>', 100).Execute(); GSUnit.assertEquals(1, docs.length); + GSUnit.assertArrayEqualsIgnoringOrder( + expected.map((p) => `${path}/${p}`), + docs.map((doc) => doc.path) + ); } Test_Query_Where_Gte_Number(): void { + const expected = ['New Document !@#$%^&*(),.<>?;\':"[]{}|-=_+áéíóúæÆÑ', 'Updatable Document Mask']; const path = 'Test Collection'; const docs = this.db.query(path).Where('number value', '>=', 100).Execute(); GSUnit.assertEquals(2, docs.length); + GSUnit.assertArrayEqualsIgnoringOrder( + expected.map((p) => `${path}/${p}`), + docs.map((doc) => doc.path) + ); } Test_Query_Where_Contains(): void { + const expected = ['New Document !@#$%^&*(),.<>?;\':"[]{}|-=_+áéíóúæÆÑ']; const path = 'Test Collection'; const docs = this.db.query(path).Where('array value', 'contains', 42).Execute(); GSUnit.assertEquals(1, docs.length); + GSUnit.assertArrayEqualsIgnoringOrder( + expected.map((p) => `${path}/${p}`), + docs.map((doc) => doc.path) + ); } Test_Query_Where_Contains_Any(): void { + const expected = ['New Document !@#$%^&*(),.<>?;\':"[]{}|-=_+áéíóúæÆÑ']; const path = 'Test Collection'; const docs = this.db.query(path).Where('array value', 'containsany', [false, 0, 42, 'bar']).Execute(); GSUnit.assertEquals(1, docs.length); + GSUnit.assertArrayEqualsIgnoringOrder( + expected.map((p) => `${path}/${p}`), + docs.map((doc) => doc.path) + ); } Test_Query_Where_In(): void { + const expected = ['New Document !@#$%^&*(),.<>?;\':"[]{}|-=_+áéíóúæÆÑ', 'Updatable Document Overwrite']; const path = 'Test Collection'; const docs = this.db.query(path).Where('number value', 'in', [0, 100, 42]).Execute(); GSUnit.assertEquals(2, docs.length); + GSUnit.assertArrayEqualsIgnoringOrder( + expected.map((p) => `${path}/${p}`), + docs.map((doc) => doc.path) + ); } Test_Query_Where_Nan(): void { @@ -345,9 +406,14 @@ class Tests implements TestManager { } Test_Query_Where_Null(): void { + const expected = ['New Document !@#$%^&*(),.<>?;\':"[]{}|-=_+áéíóúæÆÑ']; const path = 'Test Collection'; const docs = this.db.query(path).Where('null value', null).Execute(); GSUnit.assertEquals(1, docs.length); + GSUnit.assertArrayEqualsIgnoringOrder( + expected.map((p) => `${path}/${p}`), + docs.map((doc) => doc.path) + ); GSUnit.assertObjectEquals(this.expected_, docs[0].obj); } @@ -415,19 +481,20 @@ class Tests implements TestManager { } } -function RunTests_(): Shield { +function RunTests_(cacheSeconds: number): Shield { const scriptProps = PropertiesService.getUserProperties().getProperties(); const tests = new Tests(scriptProps['email'], scriptProps['key'], scriptProps['project'], 'v1'); const { pass, fail } = tests; - Object.entries(fail).forEach(([func, err]: [string, Error]) => - console.log(`Test Failed: ${func} (${err.message})\n${err.stack}`) - ); + for (const [func, err] of fail) { + console.log(`Test Failed: ${func} (${err.message})\n${err.stack}`); + } + console.log(`Completed ${pass.length + fail.size} Tests.`); return { schemaVersion: 1, label: 'tests', message: `✔ ${pass.length}, ✘ ${Object.keys(fail).length}`, color: Object.keys(fail).length ? 'red' : 'green', - cacheSeconds: 3600, // Always cache for 1 hour + cacheSeconds: cacheSeconds, // Always cache for 1 hour }; } @@ -438,7 +505,7 @@ function cacheResults_(cachedBadge: boolean): string { * which is longer than the time it takes to execute all the tests. */ const maxCache = 3600; - const results = JSON.stringify(RunTests_()); + const results = JSON.stringify(RunTests_(maxCache)); CacheService.getUserCache()!.put('Test Results', results, maxCache); // Send the min cache allowed @see {@link https://shields.io/endpoint ShieldsIO Endpoint} return results.replace(`"cacheSeconds":${maxCache}`, `"cacheSeconds":${cachedBadge ? maxCache : 300}`); diff --git a/package-lock.json b/package-lock.json index 183c198..f793a84 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,28 +1,28 @@ { "name": "firestore_google-apps-script", - "version": "1.0.32", + "version": "1.0.33", "lockfileVersion": 1, "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.10.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.3.tgz", - "integrity": "sha512-fDx9eNW0qz0WkUeqL6tXEXzVlPh6Y5aCDEZesl0xBGA8ndRukX91Uk44ZqnkECp01NAZUdCAl+aiQNGi0k88Eg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", "requires": { - "@babel/highlight": "^7.10.3" + "@babel/highlight": "^7.10.4" } }, "@babel/helper-validator-identifier": { - "version": "7.10.3", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.3.tgz", - "integrity": "sha512-bU8JvtlYpJSBPuj1VUmKpFGaDZuLxASky3LhaKj3bmpSTY6VWooSM8msk+Z0CZoErFye2tlABF6yDkT3FOPAXw==" + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==" }, "@babel/highlight": { - "version": "7.10.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.3.tgz", - "integrity": "sha512-Ih9B/u7AtgEnySE2L2F0Xm0GaM729XqqLfHkalTsbjXGyqmf/6M0Cu0WpvqueUlW+xk88BHw9Nkpj49naU+vWw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", "requires": { - "@babel/helper-validator-identifier": "^7.10.3", + "@babel/helper-validator-identifier": "^7.10.4", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -78,11 +78,11 @@ "integrity": "sha512-0sCTiXKXELOBxvZLN4krQ0FPOAA7ij+6WwvD0k/PHd9/KAkr4dXel5J9fh6F4x1FwAQILqAWkmpeuS6mjf1iKA==" }, "@typescript-eslint/eslint-plugin": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.4.0.tgz", - "integrity": "sha512-wfkpiqaEVhZIuQRmudDszc01jC/YR7gMSxa6ulhggAe/Hs0KVIuo9wzvFiDbG3JD5pRFQoqnf4m7REDsUvBnMQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.6.0.tgz", + "integrity": "sha512-ubHlHVt1lsPQB/CZdEov9XuOFhNG9YRC//kuiS1cMQI6Bs1SsqKrEmZnpgRwthGR09/kEDtr9MywlqXyyYd8GA==", "requires": { - "@typescript-eslint/experimental-utils": "3.4.0", + "@typescript-eslint/experimental-utils": "3.6.0", "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", "regexpp": "^3.0.0", @@ -91,34 +91,42 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.4.0.tgz", - "integrity": "sha512-rHPOjL43lOH1Opte4+dhC0a/+ks+8gOBwxXnyrZ/K4OTAChpSjP76fbI8Cglj7V5GouwVAGaK+xVwzqTyE/TPw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.6.0.tgz", + "integrity": "sha512-4Vdf2hvYMUnTdkCNZu+yYlFtL2v+N2R7JOynIOkFbPjf9o9wQvRwRkzUdWlFd2YiiUwJLbuuLnl5civNg5ykOQ==", "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/typescript-estree": "3.4.0", + "@typescript-eslint/types": "3.6.0", + "@typescript-eslint/typescript-estree": "3.6.0", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" } }, "@typescript-eslint/parser": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.4.0.tgz", - "integrity": "sha512-ZUGI/de44L5x87uX5zM14UYcbn79HSXUR+kzcqU42gH0AgpdB/TjuJy3m4ezI7Q/jk3wTQd755mxSDLhQP79KA==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.6.0.tgz", + "integrity": "sha512-taghDxuLhbDAD1U5Fk8vF+MnR0yiFE9Z3v2/bYScFb0N1I9SK8eKHkdJl1DAD48OGFDMFTeOTX0z7g0W6SYUXw==", "requires": { "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "3.4.0", - "@typescript-eslint/typescript-estree": "3.4.0", + "@typescript-eslint/experimental-utils": "3.6.0", + "@typescript-eslint/types": "3.6.0", + "@typescript-eslint/typescript-estree": "3.6.0", "eslint-visitor-keys": "^1.1.0" } }, + "@typescript-eslint/types": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.6.0.tgz", + "integrity": "sha512-JwVj74ohUSt0ZPG+LZ7hb95fW8DFOqBuR6gE7qzq55KDI3BepqsCtHfBIoa0+Xi1AI7fq5nCu2VQL8z4eYftqg==" + }, "@typescript-eslint/typescript-estree": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.4.0.tgz", - "integrity": "sha512-zKwLiybtt4uJb4mkG5q2t6+W7BuYx2IISiDNV+IY68VfoGwErDx/RfVI7SWL4gnZ2t1A1ytQQwZ+YOJbHHJ2rw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.6.0.tgz", + "integrity": "sha512-G57NDSABHjvob7zVV09ehWyD1K6/YUKjz5+AufObFyjNO4DVmKejj47MHjVHHlZZKgmpJD2yyH9lfCXHrPITFg==", "requires": { + "@typescript-eslint/types": "3.6.0", + "@typescript-eslint/visitor-keys": "3.6.0", "debug": "^4.1.1", - "eslint-visitor-keys": "^1.1.0", "glob": "^7.1.6", "is-glob": "^4.0.1", "lodash": "^4.17.15", @@ -126,6 +134,14 @@ "tsutils": "^3.17.1" } }, + "@typescript-eslint/visitor-keys": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.6.0.tgz", + "integrity": "sha512-p1izllL2Ubwunite0ITjubuMQRBGgjdVYwyG7lXPX8GbrA6qF0uwSRz9MnXZaHMxID4948gX0Ez8v9tUDi/KfQ==", + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, "acorn": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz", @@ -137,9 +153,9 @@ "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==" }, "ajv": { - "version": "6.12.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", - "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -148,9 +164,9 @@ } }, "ansi-colors": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", - "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==" }, "ansi-regex": { "version": "5.0.0", @@ -318,11 +334,11 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "enquirer": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.5.tgz", - "integrity": "sha512-BNT1C08P9XD0vNg3J475yIUG+mVdp9T6towYFHUv897X0KoHBjB1shyrNmhmtHWKP17iSWgo7Gqh7BBuzLZMSA==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", "requires": { - "ansi-colors": "^3.2.1" + "ansi-colors": "^4.1.1" } }, "escape-string-regexp": { @@ -331,9 +347,9 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.3.1.tgz", - "integrity": "sha512-cQC/xj9bhWUcyi/RuMbRtC3I0eW8MH0jhRELSvpKYkWep3C6YZ2OkvcvJVUeO6gcunABmzptbXBuDoXsjHmfTA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.4.0.tgz", + "integrity": "sha512-gU+lxhlPHu45H3JkEGgYhWhkR9wLHHEXC9FbWFnTlEkbKyZKWgWRLgf61E8zWmBuI6g5xKBph9ltg3NtZMVF8g==", "requires": { "@babel/code-frame": "^7.0.0", "ajv": "^6.10.0", @@ -663,9 +679,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" }, "minimatch": { "version": "3.0.4", @@ -983,9 +999,9 @@ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" }, "typescript": { - "version": "3.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.5.tgz", - "integrity": "sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==" + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.6.tgz", + "integrity": "sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw==" }, "uri-js": { "version": "4.2.2", diff --git a/package.json b/package.json index 2e6de4b..916a160 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "firestore_google-apps-script", - "version": "1.0.32", + "version": "1.0.33", "description": "A Google Apps Script library for accessing Google Cloud Firestore", "homepage": "https://github.com/grahamearley/FirestoreGoogleAppsScript", "bugs": "https://github.com/grahamearley/FirestoreGoogleAppsScript/issues", @@ -77,13 +77,13 @@ "@types/gapi.client": "^1.0.3", "@types/google-apps-script": "^1.0.14", "@types/jsonwebtoken": "^8.5.0", - "@typescript-eslint/eslint-plugin": "^3.4.0", - "@typescript-eslint/parser": "^3.4.0", - "eslint": "^7.3.1", + "@typescript-eslint/eslint-plugin": "^3.6.0", + "@typescript-eslint/parser": "^3.6.0", + "eslint": "^7.4.0", "eslint-config-prettier": "^6.11.0", "eslint-plugin-prettier": "^3.1.4", "prettier": "^2.0.5", "replace-in-file": "^6.1.0", - "typescript": "^3.9.5" + "typescript": "^3.9.6" } } diff --git a/typings/Test.d.ts b/typings/Test.d.ts index f995d77..db9e717 100644 --- a/typings/Test.d.ts +++ b/typings/Test.d.ts @@ -1,6 +1,8 @@ interface TestManager { + db: Firestore; pass: string[]; - fail: Record; + fail: Map; + expected_: Record; } /** @see {@link https://shields.io/endpoint Source} */