From a3214abca251399e765a888e61dc4884cf8f2c4f Mon Sep 17 00:00:00 2001 From: Abe Haskins Date: Fri, 21 Dec 2018 10:44:29 -0800 Subject: [PATCH 1/7] Transition to cross-env-shell --- src/deploy/lifecycleHooks.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/deploy/lifecycleHooks.js b/src/deploy/lifecycleHooks.js index 5ad213fe..899b8f34 100644 --- a/src/deploy/lifecycleHooks.js +++ b/src/deploy/lifecycleHooks.js @@ -11,13 +11,15 @@ var logger = require("../logger"); var path = require("path"); function runCommand(command, childOptions) { + var escapedCommand = command.replace(/\"/g, '\\"'); var translatedCommand = '"' + process.execPath + '" "' + - path.resolve(require.resolve("cross-env"), "..", "bin", "cross-env.js") + - '" ' + - command; + path.resolve(require.resolve("cross-env"), "..", "bin", "cross-env-shell.js") + + '" "' + + escapedCommand + + '"'; return new Promise(function(resolve, reject) { logger.info("Running command: " + command); From c95f0b79a6ea89049bc8c2762ee9c90e047aaa9b Mon Sep 17 00:00:00 2001 From: Sam Stern Date: Wed, 2 Jan 2019 13:58:48 -0800 Subject: [PATCH 2/7] Fix race condition and empty state --- src/firestore/indexes.ts | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/firestore/indexes.ts b/src/firestore/indexes.ts index 9c88a775..f2a0fec6 100644 --- a/src/firestore/indexes.ts +++ b/src/firestore/indexes.ts @@ -59,16 +59,17 @@ export class FirestoreIndexes { ); } - indexesToDeploy.forEach(async (index) => { + const indexPromises: Promise[] = []; + for (const index of indexesToDeploy) { const exists = existingIndexes.some((x) => this.indexMatchesSpec(x, index)); if (exists) { logger.debug(`Skipping existing index: ${JSON.stringify(index)}`); - return; + } else { + logger.debug(`Creating new index: ${JSON.stringify(index)}`); + indexPromises.push(this.createIndex(project, index)); } - - logger.debug(`Creating new index: ${JSON.stringify(index)}`); - await this.createIndex(project, index); - }); + } + await Promise.all(indexPromises); if (existingFieldOverrides.length > fieldOverridesToDeploy.length) { utils.logBullet( @@ -78,16 +79,17 @@ export class FirestoreIndexes { ); } - fieldOverridesToDeploy.forEach(async (field) => { + const fieldPromises: Promise[] = []; + for (const field of fieldOverridesToDeploy) { const exists = existingFieldOverrides.some((x) => this.fieldMatchesSpec(x, field)); if (exists) { logger.debug(`Skipping existing field override: ${JSON.stringify(field)}`); - return; + } else { + logger.debug(`Updating field override: ${JSON.stringify(field)}`); + fieldPromises.push(this.patchField(project, field)); } - - logger.debug(`Updating field override: ${JSON.stringify(field)}`); - await this.patchField(project, field); - }); + } + await Promise.all(fieldPromises); } /** @@ -198,6 +200,11 @@ export class FirestoreIndexes { * @param indexes the array of indexes. */ prettyPrintIndexes(indexes: API.Index[]): void { + if (indexes.length == 0) { + logger.info("None"); + return; + } + indexes.forEach((index) => { logger.info(this.prettyIndexString(index)); }); @@ -208,6 +215,11 @@ export class FirestoreIndexes { * @param fields the array of field overrides. */ printFieldOverrides(fields: API.Field[]): void { + if (fields.length == 0) { + logger.info("None"); + return; + } + fields.forEach((field) => { logger.info(this.prettyFieldString(field)); }); From 5ae5e2d86c8e7a3617453f04bcaf02d239a47e03 Mon Sep 17 00:00:00 2001 From: Sam Stern Date: Wed, 2 Jan 2019 14:35:14 -0800 Subject: [PATCH 3/7] Fix empty field bug --- src/firestore/indexes-api.ts | 2 +- src/firestore/indexes.ts | 31 ++++++++++++++++++------------ src/test/firestore/indexes.spec.ts | 15 +++++++++++++++ 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/firestore/indexes-api.ts b/src/firestore/indexes-api.ts index 1b5e8568..39f35561 100644 --- a/src/firestore/indexes-api.ts +++ b/src/firestore/indexes-api.ts @@ -65,5 +65,5 @@ export interface Field { */ export interface IndexConfig { ancestorField?: string; - indexes: Index[]; + indexes?: Index[]; } diff --git a/src/firestore/indexes.ts b/src/firestore/indexes.ts index f2a0fec6..cc163818 100644 --- a/src/firestore/indexes.ts +++ b/src/firestore/indexes.ts @@ -59,7 +59,7 @@ export class FirestoreIndexes { ); } - const indexPromises: Promise[] = []; + const indexPromises: Array> = []; for (const index of indexesToDeploy) { const exists = existingIndexes.some((x) => this.indexMatchesSpec(x, index)); if (exists) { @@ -79,7 +79,7 @@ export class FirestoreIndexes { ); } - const fieldPromises: Promise[] = []; + const fieldPromises: Array> = []; for (const field of fieldOverridesToDeploy) { const exists = existingFieldOverrides.some((x) => this.fieldMatchesSpec(x, field)); if (exists) { @@ -174,11 +174,12 @@ export class FirestoreIndexes { const fieldsJson = fields.map((field) => { const parsedName = this.parseFieldName(field.name); + const fieldIndexes = field.indexConfig.indexes || []; return { collectionGroup: parsedName.collectionGroupId, fieldPath: parsedName.fieldPath, - indexes: field.indexConfig.indexes.map((index) => { + indexes: fieldIndexes.map((index) => { const firstField = index.fields[0]; return { order: firstField.order, @@ -200,7 +201,7 @@ export class FirestoreIndexes { * @param indexes the array of indexes. */ prettyPrintIndexes(indexes: API.Index[]): void { - if (indexes.length == 0) { + if (indexes.length === 0) { logger.info("None"); return; } @@ -215,7 +216,7 @@ export class FirestoreIndexes { * @param fields the array of field overrides. */ printFieldOverrides(fields: API.Field[]): void { - if (fields.length == 0) { + if (fields.length === 0) { logger.info("None"); return; } @@ -402,11 +403,12 @@ export class FirestoreIndexes { return false; } - if (field.indexConfig.indexes.length !== spec.indexes.length) { + const fieldIndexes = field.indexConfig.indexes || []; + if (fieldIndexes.length !== spec.indexes.length) { return false; } - const fieldModes = field.indexConfig.indexes.map((index) => { + const fieldModes = fieldIndexes.map((index) => { const firstField = index.fields[0]; return firstField.order || firstField.arrayConfig; }); @@ -575,11 +577,16 @@ export class FirestoreIndexes { clc.yellow(parsedName.fieldPath) + "] --"; - field.indexConfig.indexes.forEach((index) => { - const firstField = index.fields[0]; - const mode = firstField.order || firstField.arrayConfig; - result += " (" + mode + ")"; - }); + const fieldIndexes = field.indexConfig.indexes || []; + if (fieldIndexes.length > 0) { + fieldIndexes.forEach((index) => { + const firstField = index.fields[0]; + const mode = firstField.order || firstField.arrayConfig; + result += " (" + mode + ")"; + }); + } else { + result += " (no indexes)"; + } return result; } diff --git a/src/test/firestore/indexes.spec.ts b/src/test/firestore/indexes.spec.ts index 0c32d538..b32fe31a 100644 --- a/src/test/firestore/indexes.spec.ts +++ b/src/test/firestore/indexes.spec.ts @@ -198,6 +198,21 @@ describe("IndexSpecMatching", () => { expect(idx.fieldMatchesSpec(apiField, specField)).to.eql(true); }); + it("should match a field spec with all indexes excluded", () => { + const apiField = { + name: "/projects/myproject/databases/(default)/collectionGroups/collection/fields/abc123", + indexConfig: {}, + } as API.Field; + + const specField = { + collectionGroup: "collection", + fieldPath: "abc123", + indexes: [], + } as Spec.FieldOverride; + + expect(idx.fieldMatchesSpec(apiField, specField)).to.eql(true); + }); + it("should identify a negative field spec match", () => { const apiField = { name: "/projects/myproject/databases/(default)/collectionGroups/collection/fields/abc123", From 41b2f802905c501309808119e4b0b8d50992cd15 Mon Sep 17 00:00:00 2001 From: Sam Stern Date: Thu, 3 Jan 2019 08:26:32 -0800 Subject: [PATCH 4/7] Review feedback --- src/firestore/indexes.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/firestore/indexes.ts b/src/firestore/indexes.ts index cc163818..4631a5c7 100644 --- a/src/firestore/indexes.ts +++ b/src/firestore/indexes.ts @@ -60,7 +60,7 @@ export class FirestoreIndexes { } const indexPromises: Array> = []; - for (const index of indexesToDeploy) { + indexesToDeploy.forEach((index) => { const exists = existingIndexes.some((x) => this.indexMatchesSpec(x, index)); if (exists) { logger.debug(`Skipping existing index: ${JSON.stringify(index)}`); @@ -68,7 +68,7 @@ export class FirestoreIndexes { logger.debug(`Creating new index: ${JSON.stringify(index)}`); indexPromises.push(this.createIndex(project, index)); } - } + }); await Promise.all(indexPromises); if (existingFieldOverrides.length > fieldOverridesToDeploy.length) { @@ -80,7 +80,7 @@ export class FirestoreIndexes { } const fieldPromises: Array> = []; - for (const field of fieldOverridesToDeploy) { + fieldOverridesToDeploy.forEach((field) => { const exists = existingFieldOverrides.some((x) => this.fieldMatchesSpec(x, field)); if (exists) { logger.debug(`Skipping existing field override: ${JSON.stringify(field)}`); @@ -88,7 +88,7 @@ export class FirestoreIndexes { logger.debug(`Updating field override: ${JSON.stringify(field)}`); fieldPromises.push(this.patchField(project, field)); } - } + }); await Promise.all(fieldPromises); } @@ -582,7 +582,7 @@ export class FirestoreIndexes { fieldIndexes.forEach((index) => { const firstField = index.fields[0]; const mode = firstField.order || firstField.arrayConfig; - result += " (" + mode + ")"; + result += ` (${mode})`; }); } else { result += " (no indexes)"; From 07f792c6651f4aaed2e173e6d66213276d152db5 Mon Sep 17 00:00:00 2001 From: Scott Crossen Date: Thu, 3 Jan 2019 11:49:04 -0800 Subject: [PATCH 5/7] Release Firestore Emulator v1.2.3 (#1083) Release of firestore emulator v1.2.3 --- changelog.txt | 6 ++++++ src/emulator/constants.js | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index e69de29b..908738e7 100644 --- a/changelog.txt +++ b/changelog.txt @@ -0,0 +1,6 @@ +fixed - Fixed Firestore emulator bug related to https://github.com/firebase/firebase-tools/issues/1073 +fixed - Fixed Firestore emulator bug regarding array ordering during writing/reading +fixed - Fixed Firestore emulator handling of query cursors using document names +feature - Firestore emulator now has the ability to produce rule-coverage reports +changed - Firestore emulator now exposes the v1 service definition +changed - Firestore emulator has various runtime improvements diff --git a/src/emulator/constants.js b/src/emulator/constants.js index 7996e59a..67e324db 100644 --- a/src/emulator/constants.js +++ b/src/emulator/constants.js @@ -24,8 +24,8 @@ const _emulators = { stdout: null, cacheDir: CACHE_DIR, remoteUrl: - "https://storage.googleapis.com/firebase-preview-drop/emulator/cloud-firestore-emulator-v1.2.2.jar", - localPath: path.join(CACHE_DIR, "cloud-firestore-emulator-v1.2.2.jar"), + "https://storage.googleapis.com/firebase-preview-drop/emulator/cloud-firestore-emulator-v1.2.3.jar", + localPath: path.join(CACHE_DIR, "cloud-firestore-emulator-v1.2.3.jar"), }, }; From 16273a70361330adc4543008cf4deefb2bc60561 Mon Sep 17 00:00:00 2001 From: Sam Stern Date: Thu, 3 Jan 2019 14:59:18 -0800 Subject: [PATCH 6/7] Update changelog.txt for #1082 (#1085) --- changelog.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changelog.txt b/changelog.txt index 908738e7..e38baab6 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,9 @@ fixed - Fixed Firestore emulator bug related to https://github.com/firebase/firebase-tools/issues/1073 fixed - Fixed Firestore emulator bug regarding array ordering during writing/reading fixed - Fixed Firestore emulator handling of query cursors using document names +fixed - Fixed a race condition when deploying Firestore indexes (issues #1080 and #1081) +fixed - Fixed an error that occurs when a Firestore field override removes all indexes feature - Firestore emulator now has the ability to produce rule-coverage reports changed - Firestore emulator now exposes the v1 service definition changed - Firestore emulator has various runtime improvements +changed - Clearer empty state when pretty-printing Firestore indexes \ No newline at end of file From 14cfda4a4c47d1fc41cc74f640ee4378bfb2ab9f Mon Sep 17 00:00:00 2001 From: Josep Sayol Date: Sat, 5 Jan 2019 00:29:21 +0100 Subject: [PATCH 7/7] [init functions] Wait for overwrite confirmation of tslint.json (#1074) --- src/init/features/functions/typescript.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init/features/functions/typescript.js b/src/init/features/functions/typescript.js index 0e4ea60f..70e5c47b 100644 --- a/src/init/features/functions/typescript.js +++ b/src/init/features/functions/typescript.js @@ -39,7 +39,7 @@ module.exports = function(setup, config) { return config .askWriteProjectFile("functions/package.json", PACKAGE_LINTING_TEMPLATE) .then(function() { - config.askWriteProjectFile("functions/tslint.json", TSLINT_TEMPLATE); + return config.askWriteProjectFile("functions/tslint.json", TSLINT_TEMPLATE); }); } _.set(setup, "config.functions.predeploy", 'npm --prefix "$RESOURCE_DIR" run build');