@firebase-function-kits/bigquery-firestore-export 0.0.2-rc.0 → 0.0.2-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@firebase-function-kits/bigquery-firestore-export",
3
- "version": "0.0.2-rc.0",
3
+ "version": "0.0.2-rc.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/firebase/extensions.git",
package/src/config.ts CHANGED
@@ -32,21 +32,138 @@ const instanceId = defineString("INSTANCE_ID");
32
32
  const params = {
33
33
  instanceId,
34
34
  bigqueryDatasetLocation: defineString("BIGQUERY_DATASET_LOCATION", {
35
+ label: "BigQuery Dataset Location",
36
+ description:
37
+ "What is the location of the BigQuery dataset referenced in the query?",
38
+
35
39
  default: "US",
40
+ input: select({
41
+ "Columbus, Ohio (us-east5)": "us-east5",
42
+ "Iowa (us-central1)": "us-central1",
43
+ "Las Vegas (us-west4)": "us-west4",
44
+ "Los Angeles (us-west2)": "us-west2",
45
+ "Montréal (northamerica-northeast1)": "northamerica-northeast1",
46
+ "Northern Virginia (us-east4)": "us-east4",
47
+ "Oregon (us-west1)": "us-west1",
48
+ "Salt Lake City (us-west3)": "us-west3",
49
+ "São Paulo (southamerica-east1)": "southamerica-east1",
50
+ "Santiago (southamerica-west1)": "southamerica-west1",
51
+ "South Carolina (us-east1)": "us-east1",
52
+ "Toronto (northamerica-northeast2)": "northamerica-northeast2",
53
+ "Delhi (asia-south2)": "asia-south2",
54
+ "Hong Kong (asia-east2)": "asia-east2",
55
+ "Jakarta (asia-southeast2)": "asia-southeast2",
56
+ "Melbourne (australia-southeast2)": "australia-southeast2",
57
+ "Mumbai (asia-south1)": "asia-south1",
58
+ "Osaka (asia-northeast2)": "asia-northeast2",
59
+ "Seoul (asia-northeast3)": "asia-northeast3",
60
+ "Singapore (asia-southeast1)": "asia-southeast1",
61
+ "Sydney (australia-southeast1)": "australia-southeast1",
62
+ "Taiwan (asia-east1)": "asia-east1",
63
+ "Tokyo (asia-northeast1)": "asia-northeast1",
64
+ "Belgium (europe-west1)": "europe-west1",
65
+ "Finland (europe-north1)": "europe-north1",
66
+ "Frankfurt (europe-west3)": "europe-west3",
67
+ "London (europe-west2)": "europe-west2",
68
+ "Madrid (europe-southwest1)": "europe-southwest1",
69
+ "Milan (europe-west8)": "europe-west8",
70
+ "Netherlands (europe-west4)": "europe-west4",
71
+ "Paris (europe-west9)": "europe-west9",
72
+ "Warsaw (europe-central2)": "europe-central2",
73
+ "Zürich (europe-west6)": "europe-west6",
74
+ "US Multi-Region (US)": "US",
75
+ "EU Mutli-Region (EU)": "EU",
76
+ }),
36
77
  }),
37
78
  transferConfigName: defineString("TRANSFER_CONFIG_NAME", { default: "" }),
38
- datasetId: defineString("DATASET_ID"),
39
- tableName: defineString("TABLE_NAME"),
40
- queryString: defineString("QUERY_STRING"),
41
- displayName: defineString("DISPLAY_NAME"),
42
- partitioningField: defineString("PARTITIONING_FIELD", { default: "" }),
43
- schedule: defineString("SCHEDULE"),
79
+ datasetId: defineString("DATASET_ID", {
80
+ label: "Dataset ID",
81
+ description:
82
+ "What's the BigQuery destination dataset you'd like to use? Each transfer run will write to a table in this destination dataset.",
83
+ input: {
84
+ text: {
85
+ nonEmpty: true,
86
+ example: "customer_data",
87
+ },
88
+ },
89
+ }),
90
+ tableName: defineString("TABLE_NAME", {
91
+ label: "Destination Table Name",
92
+ description:
93
+ "What's the destination table name prefix you'd like to use? Each transfer run will write to the table with this name, postfixed with the runtime.",
94
+ input: {
95
+ text: {
96
+ nonEmpty: true,
97
+ example: "transactions",
98
+ },
99
+ },
100
+ }),
101
+ queryString: defineString("QUERY_STRING", {
102
+ label: "Query String",
103
+ description: "What's the BQ query you'd like to execute?",
104
+ input: {
105
+ text: {
106
+ nonEmpty: true,
107
+
108
+ example: "SELECT * from <PROJECT_ID>.customer_data.transactions",
109
+ },
110
+ },
111
+ }),
112
+ displayName: defineString("DISPLAY_NAME", {
113
+ label: "Display Name",
114
+ description: "What display name would you like to use?",
115
+ input: {
116
+ text: {
117
+ nonEmpty: true,
118
+ example: "Daily Rollup - Customer Transactions",
119
+ },
120
+ },
121
+ }),
122
+ partitioningField: defineString("PARTITIONING_FIELD", {
123
+ label: "Partitioning Field",
124
+ description:
125
+ "What's the partitioning field on the destination table ID? Leave empty if not using a partitioning field.",
126
+ default: "",
127
+ input: { text: { example: "timestamp" } },
128
+ }),
129
+ schedule: defineString("SCHEDULE", {
130
+ label: "Schedule",
131
+ description:
132
+ "What's the execution schedule you'd like to use for this query?",
133
+ input: {
134
+ text: {
135
+ nonEmpty: true,
136
+ example: "every 15 minutes",
137
+ },
138
+ },
139
+ }),
44
140
  firestoreCollection: defineString("COLLECTION_PATH", {
141
+ label: "Firestore Collection",
142
+ description:
143
+ "What's the top-level Firestore Collection to store transfer configs, run metadata, and query output?",
144
+
45
145
  default: "transferConfigs",
146
+ input: {
147
+ text: {
148
+ example: "transferConfigs",
149
+
150
+ validationRegex: /^[^\/]+(\/[^\/]+\/[^\/]+)*$/,
151
+ validationErrorMessage: "Must be a valid Cloud Firestore Collection",
152
+ },
153
+ },
46
154
  }),
47
155
  logLevel: defineString("LOG_LEVEL", {
156
+ label: "Log Level",
157
+ description: "What's the log level you'd like to use for this extension?",
158
+
48
159
  default: "info",
49
- input: select([...LOG_LEVEL_OPTIONS]),
160
+ input: select({
161
+ DEBUG: "debug",
162
+ INFO: "info",
163
+ WARN: "warn",
164
+ ERROR: "error",
165
+ SILENT: "silent",
166
+ }),
50
167
  }),
51
168
  };
52
169
 
package/src/dts.ts CHANGED
@@ -65,10 +65,16 @@ function stringField(value: string | undefined): { stringValue: string } {
65
65
  return { stringValue: value ?? "" };
66
66
  }
67
67
 
68
- /** Creates the protobuf-shaped request used for a scheduled query. */
68
+ /**
69
+ * Creates the protobuf-shaped request used for a scheduled query.
70
+ *
71
+ * The query runs as whichever identity creates it, which is this function. To
72
+ * name a different account, `serviceAccountName` goes on the request rather
73
+ * than on the transfer config, and the caller needs `actAs` on the account it
74
+ * names, including its own.
75
+ */
69
76
  export function createTransferConfigRequest(
70
- config: ResolvedBigqueryFirestoreExportConfig,
71
- serviceAccountEmail?: string
77
+ config: ResolvedBigqueryFirestoreExportConfig
72
78
  ): bigqueryDataTransfer.protos.google.cloud.bigquery.datatransfer.v1.ICreateTransferConfigRequest {
73
79
  return {
74
80
  parent: `projects/${config.projectId}`,
@@ -88,9 +94,6 @@ export function createTransferConfigRequest(
88
94
  },
89
95
  schedule: config.schedule,
90
96
  notificationPubsubTopic: `projects/${config.projectId}/topics/${config.pubSubTopic}`,
91
- ...(serviceAccountEmail
92
- ? { serviceAccountName: serviceAccountEmail }
93
- : {}),
94
97
  },
95
98
  };
96
99
  }
@@ -120,7 +123,7 @@ export async function createTransferConfig(
120
123
  ): Promise<TransferConfig> {
121
124
  logs.createTransferConfig();
122
125
  const [created] = await client.createTransferConfig(
123
- createTransferConfigRequest(config, config.serviceAccount)
126
+ createTransferConfigRequest(config)
124
127
  );
125
128
  if (!created.name) {
126
129
  throw new Error("BigQuery API returned a transfer config without a name");
@@ -45,8 +45,6 @@ export interface BigqueryFirestoreExportConfig {
45
45
  pubSubTopic?: string;
46
46
  /** Root Firestore collection for configs and run output. */
47
47
  firestoreCollection?: string;
48
- /** Runtime identity used when creating a DTS config. */
49
- serviceAccount?: string;
50
48
  /** Log verbosity. Defaults to `info`. */
51
49
  logLevel?: LogLevel;
52
50
  }
@@ -65,7 +63,6 @@ export interface ResolvedBigqueryFirestoreExportConfig {
65
63
  schedule: string;
66
64
  pubSubTopic: string;
67
65
  firestoreCollection: string;
68
- serviceAccount?: string;
69
66
  logLevel: LogLevel;
70
67
  }
71
68
 
@@ -117,7 +114,6 @@ export function resolveConfig(
117
114
  optional(config.pubSubTopic) ?? `kit-${instanceId}-processMessages`,
118
115
  firestoreCollection:
119
116
  optional(config.firestoreCollection) ?? "transferConfigs",
120
- serviceAccount: optional(config.serviceAccount),
121
117
  logLevel,
122
118
  };
123
119
  }
package/src/index.ts CHANGED
@@ -111,7 +111,7 @@ function getContext(): HandlerContext {
111
111
  export const processMessages = onMessagePublished<TransferRunPayload>(
112
112
  {
113
113
  topic: CONFIG_EXPRESSIONS.pubSubTopic,
114
- retry: true,
114
+ retry: false,
115
115
  },
116
116
  (event) => handleMessagePublished(event, getContext())
117
117
  );
package/tests/dts.test.ts CHANGED
@@ -43,10 +43,7 @@ function clientWithTransferConfig(transferConfig: object): DataTransferClient {
43
43
 
44
44
  describe("createTransferConfigRequest", () => {
45
45
  test("creates the scheduled-query request", () => {
46
- const request = createTransferConfigRequest(
47
- config,
48
- "runtime@test-project.iam.gserviceaccount.com"
49
- );
46
+ const request = createTransferConfigRequest(config);
50
47
 
51
48
  expect(request).toMatchObject({
52
49
  parent: "projects/test-project",
@@ -57,7 +54,6 @@ describe("createTransferConfigRequest", () => {
57
54
  schedule: "every 24 hours",
58
55
  notificationPubsubTopic:
59
56
  "projects/test-project/topics/kit-users-export-processMessages",
60
- serviceAccountName: "runtime@test-project.iam.gserviceaccount.com",
61
57
  },
62
58
  });
63
59
  expect(
@@ -46,16 +46,12 @@ describe("resolveConfig", () => {
46
46
  ...minimal,
47
47
  transferConfigName: " projects/p/locations/us/transferConfigs/c ",
48
48
  partitioningField: " created_at ",
49
- serviceAccount: " runtime@test-project.iam.gserviceaccount.com ",
50
49
  });
51
50
 
52
51
  expect(resolved.transferConfigName).toBe(
53
52
  "projects/p/locations/us/transferConfigs/c"
54
53
  );
55
54
  expect(resolved.partitioningField).toBe("created_at");
56
- expect(resolved.serviceAccount).toBe(
57
- "runtime@test-project.iam.gserviceaccount.com"
58
- );
59
55
  });
60
56
 
61
57
  test.each(["instanceId", "datasetId", "tableName", "queryString"] as const)(