Skip to content

Commit ab7d229

Browse files
authored
November 21, 2019 Release
November 21, 2019 Release
2 parents 750bb0f + c044297 commit ab7d229

File tree

31 files changed

+137
-71
lines changed

31 files changed

+137
-71
lines changed

.github/CODEOWNERS

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# All documentation changes, e.g. changelogs & readmes.
2+
*.md @rachelsaunders
3+
4+
# Dependencies, package.json and mono-repo files
5+
package.json @Salakar @Ehesp
6+
*/package.json @Salakar @Ehesp
7+
lerna.json @Salakar @Ehesp
8+
9+
# Tests
10+
jest.config.js @Salakar @Ehesp
11+
*/jest.config.js @Salakar @Ehesp
12+
__tests__/* @Salakar @Ehesp

auth-mailchimp-sync/extension.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ params:
8989
value: asia-northeast1
9090
default: us-central1
9191
required: true
92+
immutable: true
9293

9394
- param: MAILCHIMP_API_KEY
9495
type: string

delete-user-data/extension.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ params:
8787
value: asia-northeast1
8888
default: us-central1
8989
required: true
90+
immutable: true
9091

9192
- param: FIRESTORE_PATHS
9293
type: string

delete-user-data/functions/lib/index.js

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@
1515
* limitations under the License.
1616
*/
1717
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
18+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
1819
return new (P || (P = Promise))(function (resolve, reject) {
1920
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
2021
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
21-
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
22+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
2223
step((generator = generator.apply(thisArg, _arguments || [])).next());
2324
});
2425
};
@@ -36,7 +37,7 @@ logs.init();
3637
* Storage, and Firestore. It waits for all deletions to complete, and then
3738
* returns a success message.
3839
*/
39-
exports.clearData = functions.auth.user().onDelete((user) => __awaiter(this, void 0, void 0, function* () {
40+
exports.clearData = functions.auth.user().onDelete((user) => __awaiter(void 0, void 0, void 0, function* () {
4041
logs.start();
4142
const { firestorePaths, rtdbPaths, storagePaths } = config_1.default;
4243
const { uid } = user;
@@ -62,10 +63,10 @@ exports.clearData = functions.auth.user().onDelete((user) => __awaiter(this, voi
6263
yield Promise.all(promises);
6364
logs.complete(uid);
6465
}));
65-
const clearDatabaseData = (databasePaths, uid) => __awaiter(this, void 0, void 0, function* () {
66+
const clearDatabaseData = (databasePaths, uid) => __awaiter(void 0, void 0, void 0, function* () {
6667
logs.rtdbDeleting();
6768
const paths = extractUserPaths(databasePaths, uid);
68-
const promises = paths.map((path) => __awaiter(this, void 0, void 0, function* () {
69+
const promises = paths.map((path) => __awaiter(void 0, void 0, void 0, function* () {
6970
try {
7071
logs.rtdbPathDeleting(path);
7172
yield admin
@@ -81,10 +82,10 @@ const clearDatabaseData = (databasePaths, uid) => __awaiter(this, void 0, void 0
8182
yield Promise.all(promises);
8283
logs.rtdbDeleted();
8384
});
84-
const clearStorageData = (storagePaths, uid) => __awaiter(this, void 0, void 0, function* () {
85+
const clearStorageData = (storagePaths, uid) => __awaiter(void 0, void 0, void 0, function* () {
8586
logs.storageDeleting();
8687
const paths = extractUserPaths(storagePaths, uid);
87-
const promises = paths.map((path) => __awaiter(this, void 0, void 0, function* () {
88+
const promises = paths.map((path) => __awaiter(void 0, void 0, void 0, function* () {
8889
const parts = path.split("/");
8990
const bucketName = parts[0];
9091
const bucket = bucketName === "{DEFAULT}"
@@ -109,20 +110,20 @@ const clearStorageData = (storagePaths, uid) => __awaiter(this, void 0, void 0,
109110
yield Promise.all(promises);
110111
logs.storageDeleted();
111112
});
112-
const clearFirestoreData = (firestorePaths, uid) => __awaiter(this, void 0, void 0, function* () {
113+
const clearFirestoreData = (firestorePaths, uid) => __awaiter(void 0, void 0, void 0, function* () {
113114
logs.firestoreDeleting();
114115
const paths = extractUserPaths(firestorePaths, uid);
115-
const promises = paths.map((path) => __awaiter(this, void 0, void 0, function* () {
116+
const promises = paths.map((path) => __awaiter(void 0, void 0, void 0, function* () {
116117
try {
117-
const isRecursive = config_1.default.firestoreDeleteMode === 'recursive';
118+
const isRecursive = config_1.default.firestoreDeleteMode === "recursive";
118119
if (!isRecursive) {
119120
const firestore = admin.firestore();
120121
logs.firestorePathDeleting(path, false);
121122
// Wrapping in transaction to allow for automatic retries (#48)
122-
yield firestore.runTransaction((transaction => {
123+
yield firestore.runTransaction((transaction) => {
123124
transaction.delete(firestore.doc(path));
124125
return Promise.resolve();
125-
}));
126+
});
126127
logs.firestorePathDeleted(path, false);
127128
}
128129
else {

delete-user-data/functions/lib/logs.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ exports.firestoreNotConfigured = () => {
2929
console.log("Cloud Firestore paths are not configured, skipping");
3030
};
3131
exports.firestorePathDeleted = (path, recursive) => {
32-
console.log(`Deleted: '${path}' from Cloud Firestore ${recursive ? 'with recursive delete' : ''}`);
32+
console.log(`Deleted: '${path}' from Cloud Firestore ${recursive ? "with recursive delete" : ""}`);
3333
};
3434
exports.firestorePathDeleting = (path, recursive) => {
35-
console.log(`Deleting: '${path}' from Cloud Firestore ${recursive ? 'with recursive delete' : ''}`);
35+
console.log(`Deleting: '${path}' from Cloud Firestore ${recursive ? "with recursive delete" : ""}`);
3636
};
3737
exports.firestorePathError = (path, err) => {
3838
console.error(`Error when deleting: '${path}' from Cloud Firestore`, err);

firestore-bigquery-export/PREINSTALL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ Learn more about using this script to [backfill your existing collection](https:
2626

2727
This extension uses other Firebase or Google Cloud Platform services which may have associated charges:
2828

29+
+ BigQuery (this extension writes to BigQuery with [streaming inserts](https://cloud.google.com/bigquery/pricing#streaming_pricing))
2930
+ Cloud Firestore
30-
+ BigQuery
3131
+ Cloud Functions
3232

3333
When you use Firebase Extensions, you're only charged for the underlying resources that you use. A paid-tier billing plan is only required if the extension uses a service that requires a paid-tier plan, for example calling to a Google Cloud Platform API or making outbound network requests to non-Google services. All Firebase services offer a free tier of usage. [Learn more about Firebase billing.](https://firebase.google.com/pricing)

firestore-bigquery-export/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ Learn more about using this script to [backfill your existing collection](https:
3232

3333
This extension uses other Firebase or Google Cloud Platform services which may have associated charges:
3434

35+
+ BigQuery (this extension writes to BigQuery with [streaming inserts](https://cloud.google.com/bigquery/pricing#streaming_pricing))
3536
+ Cloud Firestore
36-
+ BigQuery
3737
+ Cloud Functions
3838

3939
When you use Firebase Extensions, you're only charged for the underlying resources that you use. A paid-tier billing plan is only required if the extension uses a service that requires a paid-tier plan, for example calling to a Google Cloud Platform API or making outbound network requests to non-Google services. All Firebase services offer a free tier of usage. [Learn more about Firebase billing.](https://firebase.google.com/pricing)

firestore-bigquery-export/extension.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ params:
8080
value: asia-northeast1
8181
default: us-central1
8282
required: true
83+
immutable: true
8384

8485
- param: COLLECTION_PATH
8586
type: string

firestore-bigquery-export/functions/lib/config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@ exports.default = {
2020
datasetId: process.env.DATASET_ID,
2121
tableId: process.env.TABLE_ID,
2222
location: process.env.LOCATION,
23-
initialized: false
23+
initialized: false,
2424
};

firestore-bigquery-export/functions/lib/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,15 @@ exports.fsexportbigquery = functions.handler.firestore.document.onWrite((change,
3838
logs.start();
3939
try {
4040
const changeType = util_1.getChangeType(change);
41-
yield eventTracker.record([{
41+
yield eventTracker.record([
42+
{
4243
timestamp: context.timestamp,
4344
operation: changeType,
4445
documentName: context.resource.name,
4546
eventId: context.eventId,
4647
data: changeType == firestore_bigquery_change_tracker_1.ChangeType.DELETE ? undefined : change.after.data(),
47-
}]);
48+
},
49+
]);
4850
logs.complete();
4951
}
5052
catch (err) {

firestore-bigquery-export/guides/IMPORT_EXISTING_DOCUMENTS.md

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,42 @@
1+
The `fs-bq-import-collection` script is for use with the official Firebase Extension [**Export Collections to BiqQuery**](https://github.com/firebase/extensions/tree/master/firestore-bigquery-export).
2+
13
### Overview
24

3-
The import script (`fs-bq-import-collection`) can read all existing documents in a Cloud Firestore collection and insert them into the raw changelog table created by the Export Collections to BigQuery extension. The script adds a special changelog for each document with the operation of `IMPORT` and the timestamp of epoch. This ensures that any operation on an imported document supersedes the import record.
5+
The import script (`fs-bq-import-collection`) can read all existing documents in a Cloud Firestore collection and insert them into the raw changelog table created by the Export Collections to BigQuery extension. The import script adds a special changelog for each document with the operation of `IMPORT` and the timestamp of epoch. This ensures that any operation on an imported document supersedes the import record.
46

5-
You may pause and resume the script from the last batch at any point.
7+
You may pause and resume the import script from the last batch at any point.
68

79
#### Important notes
810

9-
- Run the script over the entire collection **_after_** installing the Export Collections to BigQuery extension; otherwise the writes to your database during the import might not be exported to the dataset.
11+
- You must run the import script over the entire collection **_after_** installing the Export Collections to BigQuery extension; otherwise the writes to your database during the import might not be exported to the dataset.
12+
1013
- The import script can take up to _O(collection size)_ time to finish. If your collection is large, you might want to consider [loading data from a Cloud Firestore export into BigQuery](https://cloud.google.com/bigquery/docs/loading-data-cloud-firestore).
11-
- You will see redundant rows in your raw changelog table:
1214

13-
- If document changes occur in the time between installing the extension and running this import script.
15+
- You will see redundant rows in your raw changelog table if either of the following happen:
16+
17+
- If document changes occur in the time between installing the extension and running the import script.
1418
- If you run the import script multiple times over the same collection.
1519

16-
### Install and run the script
20+
### Run the script
1721

18-
This import script uses several values from your installation of the extension:
22+
The import script uses several values from your installation of the extension:
1923

2024
- `${PROJECT_ID}`: the project ID for the Firebase project in which you installed the extension
2125
- `${COLLECTION_PATH}`: the collection path that you specified during extension installation
2226
- `${DATASET_ID}`: the ID that you specified for your dataset during extension installation
2327

24-
1. Run `npx @firebaseextensions/fs-bq-import-collection`.
28+
Run the import script using [`npx` (the Node Package Runner)](https://www.npmjs.com/package/npx) via `npm` (the Node Package Manager).
29+
30+
1. Make sure that you've installed the required tools to run the import script:
31+
32+
- To access the `npm` command tools, you need to install [Node.js](https://www.nodejs.org/).
33+
- If you use `npm` v5.1 or earlier, you need to explicitly install `npx`. Run `npm install --global npx`.
34+
35+
1. Run the import script via `npx` by running the following command:
36+
37+
```
38+
npx @firebaseextensions/fs-bq-import-collection
39+
```
2540
2641
1. When prompted, enter the Cloud Firestore collection path that you specified during extension installation, `${COLLECTION_PATH}`.
2742

firestore-counter/extension.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ params:
100100
value: asia-northeast1
101101
default: us-central1
102102
required: true
103+
immutable: true
103104

104105
- param: INTERNAL_STATE_PATH
105106
label: Document path for internal state

firestore-send-email/extension.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ params:
7878
value: asia-northeast1
7979
default: us-central1
8080
required: true
81+
immutable: true
8182

8283
- param: SMTP_CONNECTION_URI
8384
type: string

firestore-send-email/functions/lib/index.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ function validateFieldArray(field, array) {
5959
function processCreate(snap) {
6060
return __awaiter(this, void 0, void 0, function* () {
6161
// Wrapping in transaction to allow for automatic retries (#48)
62-
return admin.firestore().runTransaction((transaction => {
62+
return admin.firestore().runTransaction((transaction) => {
6363
transaction.update(snap.ref, {
6464
delivery: {
6565
startTime: admin.firestore.FieldValue.serverTimestamp(),
@@ -69,7 +69,7 @@ function processCreate(snap) {
6969
},
7070
});
7171
return Promise.resolve();
72-
}));
72+
});
7373
});
7474
}
7575
function preparePayload(payload) {
@@ -216,10 +216,10 @@ function deliver(payload, ref) {
216216
logs.deliveryError(ref, e);
217217
}
218218
// Wrapping in transaction to allow for automatic retries (#48)
219-
return admin.firestore().runTransaction((transaction => {
219+
return admin.firestore().runTransaction((transaction) => {
220220
transaction.update(ref, update);
221221
return Promise.resolve();
222-
}));
222+
});
223223
});
224224
}
225225
function processWrite(change) {
@@ -242,25 +242,25 @@ function processWrite(change) {
242242
case "PROCESSING":
243243
if (payload.delivery.leaseExpireTime.toMillis() < Date.now()) {
244244
// Wrapping in transaction to allow for automatic retries (#48)
245-
return admin.firestore().runTransaction((transaction => {
245+
return admin.firestore().runTransaction((transaction) => {
246246
transaction.update(change.after.ref, {
247247
"delivery.state": "ERROR",
248248
error: "Message processing lease expired.",
249249
});
250250
return Promise.resolve();
251-
}));
251+
});
252252
}
253253
return null;
254254
case "PENDING":
255255
case "RETRY":
256256
// Wrapping in transaction to allow for automatic retries (#48)
257-
yield admin.firestore().runTransaction((transaction => {
257+
yield admin.firestore().runTransaction((transaction) => {
258258
transaction.update(change.after.ref, {
259259
"delivery.state": "PROCESSING",
260260
"delivery.leaseExpireTime": admin.firestore.Timestamp.fromMillis(Date.now() + 60000),
261261
});
262262
return Promise.resolve();
263-
}));
263+
});
264264
return deliver(payload, change.after.ref);
265265
}
266266
});

firestore-send-email/functions/lib/logs.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,6 @@ function missingDeliveryField(ref) {
5252
}
5353
exports.missingDeliveryField = missingDeliveryField;
5454
function missingUids(uids) {
55-
console.log(`The following uids were provided, however a document does not exist or has no 'email' field: ${uids.join(',')}`);
55+
console.log(`The following uids were provided, however a document does not exist or has no 'email' field: ${uids.join(",")}`);
5656
}
5757
exports.missingUids = missingUids;

firestore-send-email/functions/lib/templates.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class Templates {
6060
console.log(`loaded template '${doc.id}'`);
6161
});
6262
this.ready = true;
63-
this.waits.forEach(wait => wait());
63+
this.waits.forEach((wait) => wait());
6464
}
6565
render(name, data) {
6666
return __awaiter(this, void 0, void 0, function* () {

firestore-shorten-urls-bitly/extension.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ params:
7979
value: asia-northeast1
8080
default: us-central1
8181
required: true
82+
immutable: true
83+
8284
- param: BITLY_ACCESS_TOKEN
8385
label: Bitly access token
8486
description: >

firestore-shorten-urls-bitly/functions/lib/abstract-shortener.js

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,10 @@
1515
* limitations under the License.
1616
*/
1717
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
18-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
1918
return new (P || (P = Promise))(function (resolve, reject) {
2019
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
2120
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
22-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
21+
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
2322
step((generator = generator.apply(thisArg, _arguments || [])).next());
2423
});
2524
};
@@ -70,7 +69,6 @@ class FirestoreUrlShortener {
7069
extractUrl(snapshot) {
7170
return snapshot.get(this.urlFieldName);
7271
}
73-
;
7472
getChangeType(change) {
7573
if (!change.after.exists) {
7674
return ChangeType.DELETE;
@@ -80,7 +78,6 @@ class FirestoreUrlShortener {
8078
}
8179
return ChangeType.UPDATE;
8280
}
83-
;
8481
handleCreateDocument(snapshot) {
8582
return __awaiter(this, void 0, void 0, function* () {
8683
const url = this.extractUrl(snapshot);
@@ -93,11 +90,9 @@ class FirestoreUrlShortener {
9390
}
9491
});
9592
}
96-
;
9793
handleDeleteDocument() {
9894
this.logs.documentDeleted();
9995
}
100-
;
10196
handleUpdateDocument(before, after) {
10297
return __awaiter(this, void 0, void 0, function* () {
10398
const urlAfter = this.extractUrl(after);
@@ -118,18 +113,16 @@ class FirestoreUrlShortener {
118113
}
119114
});
120115
}
121-
;
122116
updateShortUrl(snapshot, url) {
123117
return __awaiter(this, void 0, void 0, function* () {
124118
this.logs.updateDocument(snapshot.ref.path);
125119
// Wrapping in transaction to allow for automatic retries (#48)
126-
yield admin.firestore().runTransaction((transaction => {
120+
yield admin.firestore().runTransaction((transaction) => {
127121
transaction.update(snapshot.ref, this.shortUrlFieldName, url);
128122
return Promise.resolve();
129-
}));
123+
});
130124
this.logs.updateDocumentComplete(snapshot.ref.path);
131125
});
132126
}
133-
;
134127
}
135128
exports.FirestoreUrlShortener = FirestoreUrlShortener;

0 commit comments

Comments
 (0)