mirror of
https://github.com/zhigang1992/firebase-tools.git
synced 2026-01-12 09:04:01 +08:00
Merge branch 'master' into patch-1
This commit is contained in:
@@ -0,0 +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
|
||||
@@ -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);
|
||||
|
||||
@@ -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"),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -65,5 +65,5 @@ export interface Field {
|
||||
*/
|
||||
export interface IndexConfig {
|
||||
ancestorField?: string;
|
||||
indexes: Index[];
|
||||
indexes?: Index[];
|
||||
}
|
||||
|
||||
@@ -59,16 +59,17 @@ export class FirestoreIndexes {
|
||||
);
|
||||
}
|
||||
|
||||
indexesToDeploy.forEach(async (index) => {
|
||||
const indexPromises: Array<Promise<any>> = [];
|
||||
indexesToDeploy.forEach((index) => {
|
||||
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: Array<Promise<any>> = [];
|
||||
fieldOverridesToDeploy.forEach((field) => {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,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,
|
||||
@@ -198,6 +201,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 +216,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));
|
||||
});
|
||||
@@ -390,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;
|
||||
});
|
||||
@@ -563,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;
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user