Skip to content

Commit f0502ef

Browse files
authored
update import script with change-tracker interface changes (#354)
* udpate import script * update table prompt to match extension install prompt * add bigquery dataset/tablename and firestore collection path validation * change validateInput value type to string
1 parent 15193a5 commit f0502ef

File tree

1 file changed

+21
-26
lines changed
  • firestore-bigquery-export/scripts/import/src

1 file changed

+21
-26
lines changed

firestore-bigquery-export/scripts/import/src/index.ts

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,16 @@ const unlink = util.promisify(fs.unlink);
3737
const BIGQUERY_VALID_CHARACTERS = /^[a-zA-Z0-9_]+$/;
3838
const FIRESTORE_VALID_CHARACTERS = /^[^\/]+$/;
3939

40-
const validateInput = (value: any, name: string, regex: RegExp) => {
40+
const FIRESTORE_COLLECTION_NAME_MAX_CHARS = 6144;
41+
const BIGQUERY_RESOURCE_NAME_MAX_CHARS = 1024;
42+
43+
const validateInput = (value: string, name: string, regex: RegExp, sizeLimit: number) => {
4144
if (!value || value === "" || value.trim() === "") {
4245
return `Please supply a ${name}`;
4346
}
47+
if (value.length >= sizeLimit) {
48+
return `${name} must be at most ${sizeLimit} characters long`;
49+
}
4450
if (!value.match(regex)) {
4551
return `The ${name} must only contain letters or spaces`;
4652
}
@@ -53,36 +59,31 @@ const questions = [
5359
name: "projectId",
5460
type: "input",
5561
validate: (value) =>
56-
validateInput(value, "project ID", FIRESTORE_VALID_CHARACTERS),
62+
validateInput(value, "project ID", FIRESTORE_VALID_CHARACTERS, FIRESTORE_COLLECTION_NAME_MAX_CHARS),
5763
},
5864
{
5965
message: "What is the path of the the Cloud Firestore Collection you would like to import from? " +
6066
"(This may, or may not, be the same Collection for which you plan to mirror changes.)",
6167
name: "sourceCollectionPath",
6268
type: "input",
6369
validate: (value) =>
64-
validateInput(value, "collection path", FIRESTORE_VALID_CHARACTERS),
70+
validateInput(value, "collection path", FIRESTORE_VALID_CHARACTERS, FIRESTORE_COLLECTION_NAME_MAX_CHARS),
6571
},
6672
{
6773
message:
68-
"What is the ID of the BigQuery dataset that you would like to use? (The dataset will be created if it doesn't already exist)",
74+
"What is the ID of the BigQuery dataset that you would like to use? (A dataset will be created if it doesn't already exist)",
6975
name: "datasetId",
7076
type: "input",
7177
validate: (value) =>
72-
validateInput(value, "dataset", BIGQUERY_VALID_CHARACTERS),
78+
validateInput(value, "dataset", BIGQUERY_VALID_CHARACTERS, BIGQUERY_RESOURCE_NAME_MAX_CHARS),
7379
},
74-
];
75-
76-
const questionsRemaining = (sourceCollectionPath: string) => ([
7780
{
7881
message:
79-
"What is the name of the Cloud Firestore Collection you are mirroring? " +
80-
"(Documents in the source Collection will be written to the raw changelog for this Collection.)",
81-
name: "destinationCollectionPath",
82+
"What is the identifying prefix of the BigQuery table that you would like to import to? (A table will be created if one doesn't already exist)",
83+
name: "tableId",
8284
type: "input",
83-
default: sourceCollectionPath,
8485
validate: (value) =>
85-
validateInput(value, "dataset", BIGQUERY_VALID_CHARACTERS),
86+
validateInput(value, "table", BIGQUERY_VALID_CHARACTERS, BIGQUERY_RESOURCE_NAME_MAX_CHARS),
8687
},
8788
{
8889
message:
@@ -94,27 +95,19 @@ const questionsRemaining = (sourceCollectionPath: string) => ([
9495
return parseInt(value, 10) > 0
9596
}
9697
},
97-
]);
98+
];
9899

99100
const run = async (): Promise<number> => {
100101
const {
101102
projectId,
102103
sourceCollectionPath,
103104
datasetId,
104-
} = await inquirer.prompt(questions);
105-
/*
106-
* We use a separate inquirer prompt so that we can treat the
107-
* sourceCollectionPath as the default destinationCollectionPath. This
108-
* corresponds to the common use case in which the caller is import documents
109-
* from a collection that caller later plans to mirror changes for.
110-
*/
111-
const {
112-
destinationCollectionPath,
105+
tableId,
113106
batchSize,
114-
} = await inquirer.prompt(questionsRemaining(sourceCollectionPath));
107+
} = await inquirer.prompt(questions);
115108

116109
const batch = parseInt(batchSize);
117-
const rawChangeLogName = `${destinationCollectionPath}_raw_changelog`;
110+
const rawChangeLogName = `${tableId}_raw_changelog`;
118111

119112
// Initialize Firebase
120113
firebase.initializeApp({
@@ -125,8 +118,10 @@ const run = async (): Promise<number> => {
125118
process.env.PROJECT_ID = projectId;
126119
process.env.GOOGLE_CLOUD_PROJECT = projectId;
127120

121+
// We pass in the application-level "tableId" here. The tracker determines
122+
// the name of the raw changelog from this field.
128123
const dataSink = new FirestoreBigQueryEventHistoryTracker({
129-
tableId: destinationCollectionPath,
124+
tableId: tableId,
130125
datasetId: datasetId,
131126
});
132127

0 commit comments

Comments
 (0)