@firebase-function-kits/bigquery-firestore-export 0.0.1 → 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.
Files changed (63) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/README.md +308 -0
  3. package/lib/config.d.ts +5 -0
  4. package/lib/config.d.ts.map +1 -0
  5. package/lib/config.js +181 -0
  6. package/lib/config.js.map +1 -0
  7. package/lib/dts.d.ts +21 -0
  8. package/lib/dts.d.ts.map +1 -0
  9. package/lib/dts.js +193 -0
  10. package/lib/dts.js.map +1 -0
  11. package/lib/export-config.d.ts +55 -0
  12. package/lib/export-config.d.ts.map +1 -0
  13. package/lib/export-config.js +55 -0
  14. package/lib/export-config.js.map +1 -0
  15. package/lib/handlers.d.ts +22 -0
  16. package/lib/handlers.d.ts.map +1 -0
  17. package/lib/handlers.js +125 -0
  18. package/lib/handlers.js.map +1 -0
  19. package/lib/helper.d.ts +37 -0
  20. package/lib/helper.d.ts.map +1 -0
  21. package/lib/helper.js +219 -0
  22. package/lib/helper.js.map +1 -0
  23. package/lib/index.d.ts +7 -0
  24. package/lib/index.d.ts.map +1 -0
  25. package/lib/index.js +137 -0
  26. package/lib/index.js.map +1 -0
  27. package/lib/lib.d.ts +11 -0
  28. package/lib/lib.d.ts.map +1 -0
  29. package/lib/lib.js +47 -0
  30. package/lib/lib.js.map +1 -0
  31. package/lib/logs.d.ts +21 -0
  32. package/lib/logs.d.ts.map +1 -0
  33. package/lib/logs.js +122 -0
  34. package/lib/logs.js.map +1 -0
  35. package/lib/metadata.d.ts +6 -0
  36. package/lib/metadata.d.ts.map +1 -0
  37. package/lib/metadata.js +34 -0
  38. package/lib/metadata.js.map +1 -0
  39. package/lib/types.d.ts +44 -0
  40. package/lib/types.d.ts.map +1 -0
  41. package/lib/types.js +18 -0
  42. package/lib/types.js.map +1 -0
  43. package/npm-shrinkwrap.json +5049 -0
  44. package/package.json +40 -4
  45. package/src/config.ts +205 -0
  46. package/src/dts.ts +217 -0
  47. package/src/export-config.ts +119 -0
  48. package/src/handlers.ts +141 -0
  49. package/src/helper.ts +320 -0
  50. package/src/index.ts +126 -0
  51. package/src/lib.ts +69 -0
  52. package/src/logs.ts +145 -0
  53. package/src/metadata.ts +31 -0
  54. package/src/types.ts +100 -0
  55. package/tests/config.test.ts +61 -0
  56. package/tests/dts.test.ts +120 -0
  57. package/tests/export-config.test.ts +74 -0
  58. package/tests/handlers.test.ts +170 -0
  59. package/tests/helper.test.ts +74 -0
  60. package/tests/lib.test.ts +43 -0
  61. package/tsconfig.json +18 -0
  62. package/tsconfig.tsbuildinfo +1 -0
  63. package/index.js +0 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1 @@
1
+ - Initial release of kit, see README for differences between the legacy extension and this kit
package/README.md ADDED
@@ -0,0 +1,308 @@
1
+ # @firebase/bigquery-firestore-export
2
+
3
+ Schedule a BigQuery query and write each run's rows and metadata to Firestore.
4
+ This is the Export BigQuery to Firestore Firebase Extension as an npm package
5
+ you add to your own Firebase Functions codebase and deploy.
6
+
7
+ The kit creates or reconciles a BigQuery Data Transfer scheduled query, listens
8
+ for its Pub/Sub completion notifications, reads the destination table, and
9
+ writes the rows to Firestore. The functions run in your own Firebase project;
10
+ there is no hosted version, so you deploy them yourself.
11
+
12
+ ## Install
13
+
14
+ ```sh
15
+ npm install @firebase/bigquery-firestore-export
16
+ ```
17
+
18
+ ## Required IAM
19
+
20
+ Deploy needs these Google Cloud roles and APIs for the function's service
21
+ account. Firebase CLI 15.23.0 or later creates that account, grants the roles
22
+ below, enables the listed APIs, and attaches the account to every function in
23
+ this kit. Do not set a custom runtime service account for this codebase—it
24
+ conflicts with that automatic setup.
25
+
26
+ | Role / API | Why |
27
+ | ------------------------------------- | ------------------------------------------------------------------- |
28
+ | `roles/datastore.user` | store transfer configs, run metadata, and query output in Firestore |
29
+ | `roles/bigquery.admin` | create scheduled queries and read their destination tables |
30
+ | `roles/pubsub.admin` | create the transfer-notification topic |
31
+ | `roles/eventarc.eventReceiver` | receive Gen2 Pub/Sub trigger events |
32
+ | `roles/run.invoker` | allow Eventarc/Tasks to invoke the Gen2 Cloud Run services |
33
+ | `bigquery.googleapis.com` | run queries and read destination tables |
34
+ | `bigquerydatatransfer.googleapis.com` | create and reconcile scheduled-query transfer configs |
35
+ | `pubsub.googleapis.com` | deliver transfer-completion notifications |
36
+
37
+ ## Usage
38
+
39
+ Export both functions from your functions codebase entry:
40
+
41
+ ```ts
42
+ // functions/src/index.ts
43
+ export {
44
+ processMessages,
45
+ upsertTransferConfig,
46
+ } from "@firebase/bigquery-firestore-export";
47
+ ```
48
+
49
+ and configure them with a `.env` (or `.env.<projectId>`):
50
+
51
+ ```sh
52
+ INSTANCE_ID=analytics-export
53
+ BIGQUERY_DATASET_LOCATION=US
54
+ DATASET_ID=analytics
55
+ TABLE_NAME=users
56
+ QUERY_STRING=SELECT * FROM `my-project.source.users`
57
+ DISPLAY_NAME=Export users to Firestore
58
+ SCHEDULE=every 24 hours
59
+ ```
60
+
61
+ - `processMessages` consumes BigQuery Data Transfer completion messages.
62
+ - `upsertTransferConfig` is the idempotent lifecycle task that creates, links,
63
+ or updates the scheduled query and its notification topic.
64
+
65
+ Importing the package without exporting its functions deploys nothing—the CLI
66
+ only deploys what your entry file exports.
67
+
68
+ ## Deploy
69
+
70
+ The package's `firebase.json` declares a `kit` stanza (Firebase CLI 15.25.1 or
71
+ later, behind the `kits` experiment):
72
+
73
+ ```json
74
+ {
75
+ "functions": [
76
+ {
77
+ "source": ".",
78
+ "kit": "bigquery-firestore-export",
79
+ "instances": {
80
+ "default": "."
81
+ }
82
+ }
83
+ ]
84
+ }
85
+ ```
86
+
87
+ `instances` maps each instance id to the directory (relative to
88
+ `firebase.json`) holding that instance's `.env`. The CLI prefixes every
89
+ function and task queue name with `kit-<instance id>-`, so the functions above
90
+ deploy as `kit-default-processMessages` and
91
+ `kit-default-upsertTransferConfig`.
92
+
93
+ ```sh
94
+ firebase experiments:enable kits
95
+ firebase deploy --only functions
96
+ ```
97
+
98
+ Deploy a single instance with `firebase deploy --only functions:<instance id>`.
99
+
100
+ ## Configuration
101
+
102
+ Set these values in a `.env` (or `.env.<projectId>`) file. The Firebase CLI
103
+ loads them at deploy time and prompts for required values that are missing.
104
+ `PROJECT_ID` is supplied by the Firebase CLI.
105
+
106
+ | Field | Env var | Required | Default | Description |
107
+ | ------------------------- | --------------------------- | -------- | ----------------- | ------------------------------------------------------------ |
108
+ | `instanceId` | `INSTANCE_ID` | yes | — | Must match this instance's key in the `instances` map |
109
+ | `bigqueryDatasetLocation` | `BIGQUERY_DATASET_LOCATION` | no | `US` | BigQuery destination dataset location |
110
+ | `transferConfigName` | `TRANSFER_CONFIG_NAME` | no | (empty) | Existing DTS config resource to link instead of creating one |
111
+ | `datasetId` | `DATASET_ID` | yes | — | BigQuery destination dataset id |
112
+ | `tableName` | `TABLE_NAME` | yes | — | Prefix for per-run destination tables |
113
+ | `queryString` | `QUERY_STRING` | yes | — | Scheduled Standard SQL query |
114
+ | `displayName` | `DISPLAY_NAME` | yes | — | Human-readable scheduled-query name |
115
+ | `partitioningField` | `PARTITIONING_FIELD` | no | (empty) | Destination-table partitioning field |
116
+ | `schedule` | `SCHEDULE` | yes | — | DTS schedule, such as `every 24 hours` |
117
+ | `firestoreCollection` | `COLLECTION_PATH` | no | `transferConfigs` | Root Firestore collection for configs and output |
118
+ | `logLevel` | `LOG_LEVEL` | no | `info` | `debug`, `info`, `warn`, `error`, or `silent` |
119
+
120
+ ## Multiple instances
121
+
122
+ To run several reverse-sync instances, add one entry per instance to the
123
+ `instances` map, each pointing at its own config directory with its own `.env`:
124
+
125
+ ```json
126
+ {
127
+ "functions": [
128
+ {
129
+ "source": ".",
130
+ "kit": "bigquery-firestore-export",
131
+ "instances": {
132
+ "users": "instances/users",
133
+ "orders": "instances/orders"
134
+ }
135
+ }
136
+ ]
137
+ }
138
+ ```
139
+
140
+ Instance ids must be unique across all kit stanzas in the project, and every
141
+ instance's function names are namespaced by its `kit-<instance id>-` prefix, so
142
+ the instances cannot collide. Set `INSTANCE_ID` in each config directory to the
143
+ same value as that directory's key in the `instances` map; it also namespaces
144
+ the Pub/Sub notification topic and associates the deployment with its transfer
145
+ config.
146
+
147
+ ## Provisioning
148
+
149
+ The kit wires `upsertTransferConfig` to both `afterFirstDeploy` and
150
+ `afterRedeploy`. The lifecycle task creates the Pub/Sub topic and scheduled
151
+ query on first deploy, then reconciles supported query, table, schedule,
152
+ dataset, partitioning, and topic changes on later deploys. It retries transient
153
+ failures up to five times with at least 30 seconds of backoff.
154
+
155
+ Set `TRANSFER_CONFIG_NAME` to link an existing scheduled-query config without
156
+ changing it. Otherwise the kit stores `extInstanceId` on the Firestore config
157
+ document and uses that value to find the config on later deploys. BigQuery DTS
158
+ does not support clearing a partitioning field once set; create a new transfer
159
+ config to remove partitioning.
160
+
161
+ ## Firestore layout
162
+
163
+ For a transfer config `{configId}` and run `{runId}`, the kit writes:
164
+
165
+ ```text
166
+ transferConfigs/{configId}
167
+ transferConfigs/{configId}/runs/{runId}
168
+ transferConfigs/{configId}/runs/{runId}/output/{rowId}
169
+ transferConfigs/{configId}/runs/latest
170
+ ```
171
+
172
+ The run document stores DTS metadata and row counts. Its `output` subcollection
173
+ contains converted query rows. The `latest` document is updated transactionally
174
+ so an older completion message cannot replace a newer run.
175
+
176
+ ## Differences from the Export BigQuery to Firestore extension
177
+
178
+ This kit is version 0.2.2 of the extension repackaged as an npm package. It is a
179
+ close port: the same two functions, the same BigQuery Data Transfer scheduled
180
+ query, the same `transferConfigs/{configId}/runs/{runId}` and `runs/latest`
181
+ documents, the same `WRITE_TRUNCATE` destination table naming and the same
182
+ row-by-row copy into Firestore. Every setting keeps its extension environment
183
+ variable name and default, so a `.env` copied from your installed instance needs
184
+ no value changes. What changes is the instance id, the Pub/Sub topic, the identity
185
+ the scheduled query runs as, and how repeated BigQuery columns land in Firestore.
186
+
187
+ ### You set `INSTANCE_ID` yourself, and the Pub/Sub topic is renamed
188
+
189
+ The extension derived an instance id at install and used it to name its
190
+ notification topic (`ext-<instance id>-processMessages`) and to tag its transfer
191
+ config document with `extInstanceId`. Here `INSTANCE_ID` is a setting you
192
+ provide, and it must match this instance's key in the `instances` map in
193
+ `firebase.json`.
194
+
195
+ The topic becomes `kit-<INSTANCE_ID>-processMessages`, and the kit creates it on
196
+ first run if it does not already exist. Set `INSTANCE_ID` to your installed
197
+ instance's id if you want the kit to adopt the scheduled query that instance
198
+ created, because the lookup is by `extInstanceId` on the documents in
199
+ `COLLECTION_PATH`. With a different id the kit finds nothing, creates a second
200
+ scheduled query, and you end up with two writing into the same collection.
201
+
202
+ The existing transfer config still points its notifications at the old `ext-`
203
+ topic; the kit's update path rewrites `notification_pubsub_topic` to the new one
204
+ on the first deploy, so the old topic can be deleted afterwards.
205
+
206
+ ### Repeated BigQuery columns are now written as arrays
207
+
208
+ A repeated (`ARRAY`) column used to arrive in Firestore as a map keyed by
209
+ position, `{ "0": ..., "1": ... }`, because the conversion treated every
210
+ non-scalar value as an object. The kit writes a real Firestore array instead.
211
+ Anything reading those fields by numeric string key needs updating, and rows
212
+ written before and after the change are not the same shape. Scalars, timestamps,
213
+ dates, times, datetimes, bytes and geography values convert exactly as before.
214
+
215
+ ### The scheduled query runs as a different service account
216
+
217
+ The extension created the transfer config with
218
+ `serviceAccountName: ext-<instance id>@<project>.iam.gserviceaccount.com`, so the
219
+ query ran as the extension's own service account. The kit creates it without a
220
+ service account name, so BigQuery Data Transfer runs it as the identity that
221
+ created it, which is your function's runtime service account (the default compute
222
+ service account unless you have set one).
223
+
224
+ That account needs to be able to read whatever `QUERY_STRING` touches and write
225
+ to `DATASET_ID`. `roles/bigquery.admin` on the function covers this for datasets
226
+ in the same project; a cross-project query needs the grant made explicitly. This
227
+ was not exercised against a live deploy.
228
+
229
+ Note also that a service account cannot be changed on an existing transfer config,
230
+ so a scheduled query originally created by an installed extension instance keeps
231
+ running as the extension's service account even after the kit adopts it. Delete
232
+ and recreate the scheduled query if you want it moved.
233
+
234
+ ### The setup step runs on every deploy
235
+
236
+ The install, update and configure hooks are replaced by an `upsertTransferConfig`
237
+ task that the CLI runs after your first deploy and after every redeploy. It does
238
+ the same work: create the scheduled query if this instance has none, otherwise
239
+ reconcile the existing one against your current `QUERY_STRING`, `DATASET_ID`,
240
+ `TABLE_NAME`, `PARTITIONING_FIELD` and `SCHEDULE`.
241
+
242
+ Two consequences of it now being an ordinary task rather than a lifecycle event.
243
+ There is no install UI to report progress into, so failures show up in the task's
244
+ function logs, and the task retries up to five times with a 30 second minimum
245
+ backoff. And `DISPLAY_NAME` is no longer immutable, but changing it does not
246
+ rename an existing scheduled query, because display name is not part of the
247
+ update; it only applies to a config the kit creates.
248
+
249
+ Removing `PARTITIONING_FIELD` once it has been set still fails, with the same
250
+ explanation, because the BigQuery Data Transfer API cannot clear it.
251
+
252
+ ### You can link an existing scheduled query
253
+
254
+ `TRANSFER_CONFIG_NAME` is a new setting. Point it at the full resource name of a
255
+ scheduled query you already have
256
+ (`projects/<project>/locations/<location>/transferConfigs/<id>`) and the kit
257
+ records that config in Firestore and consumes its notifications instead of
258
+ creating one of its own. The extension carried the code for this but no setting to
259
+ reach it. Leave it empty for the create-or-reconcile behaviour described above.
260
+
261
+ ### Region, and no location setting
262
+
263
+ `LOCATION` is gone. Both functions deploy to your codebase's default region
264
+ (`us-central1` unless you have changed it) rather than the immutable location you
265
+ picked at install. `BIGQUERY_DATASET_LOCATION` is unchanged and still tells the
266
+ result query where your dataset lives.
267
+
268
+ ### Failed notifications are retried
269
+
270
+ `processMessages` is a 2nd gen Pub/Sub function with retries enabled, where the
271
+ extension's 1st gen trigger did not retry. A run whose results fail to copy, for
272
+ example because BigQuery or Firestore is briefly unavailable, is now retried
273
+ rather than dropped. A notification that keeps failing, such as one for a transfer
274
+ config not tagged with this `INSTANCE_ID`, is also retried until Pub/Sub gives up.
275
+
276
+ Both functions' service accounts need `roles/eventarc.eventReceiver` and
277
+ `roles/run.invoker` on top of the three roles the extension asked for, and the
278
+ Pub/Sub API is now requested explicitly. The Firebase CLI handles all of this.
279
+
280
+ ### Unchanged
281
+
282
+ - `COLLECTION_PATH` still defaults to `transferConfigs`, and the document layout
283
+ under it is identical: the transfer config document keyed by config id, a `runs`
284
+ subcollection keyed by run id holding `runMetadata`, `totalRowCount` and
285
+ `failedRowCount`, a `latest` document, and an `output` collection of rows per
286
+ run.
287
+ - The destination table is still `TABLE_NAME_{run_time|"%H%M%S"}` with
288
+ `WRITE_TRUNCATE`, and results are still read with `SELECT *` in
289
+ `BIGQUERY_DATASET_LOCATION`.
290
+ - Runs that do not succeed still write a run document with zeroed counts and still
291
+ update `latest`, and `latest` is still only moved forward by a newer run.
292
+ - Rows are still written one document at a time in chunks of 10,000, with
293
+ per-row failures logged and counted rather than aborting the run.
294
+ - `LOG_LEVEL` still accepts `debug`, `info`, `warn`, `error` and `silent`.
295
+
296
+ ## API surface
297
+
298
+ - **Main entry** (`@firebase/bigquery-firestore-export`): exports
299
+ `processMessages` and `upsertTransferConfig`, registers first-deploy and
300
+ redeploy lifecycle hooks, and resolves runtime dependencies lazily. Use this
301
+ entry from Firebase deploy/emulator/runtime.
302
+ - **Library entry** (`./lib`): side-effect-free config helpers, DTS helpers,
303
+ injectable handlers, BigQuery-to-Firestore conversion helpers, and public
304
+ message/config types for consumers that own trigger registration.
305
+
306
+ ## License
307
+
308
+ Apache-2.0
@@ -0,0 +1,5 @@
1
+ import type { BigqueryFirestoreExportConfig, DeployTimeOptions } from "./export-config";
2
+ export declare const CONFIG_EXPRESSIONS: DeployTimeOptions;
3
+ /** Reads runtime values from Firebase deploy-time parameters. */
4
+ export declare function configFromEnv(): BigqueryFirestoreExportConfig;
5
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EACV,6BAA6B,EAC7B,iBAAiB,EAElB,MAAM,iBAAiB,CAAC;AA+IzB,eAAO,MAAM,kBAAkB,EAAE,iBAEhC,CAAC;AAcF,iEAAiE;AACjE,wBAAgB,aAAa,IAAI,6BAA6B,CAkB7D"}
package/lib/config.js ADDED
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright 2026 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * https://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.CONFIG_EXPRESSIONS = void 0;
19
+ exports.configFromEnv = configFromEnv;
20
+ const params_1 = require("firebase-functions/params");
21
+ const LOG_LEVEL_OPTIONS = ["debug", "info", "warn", "error", "silent"];
22
+ const instanceId = (0, params_1.defineString)("INSTANCE_ID");
23
+ const params = {
24
+ instanceId,
25
+ bigqueryDatasetLocation: (0, params_1.defineString)("BIGQUERY_DATASET_LOCATION", {
26
+ label: "BigQuery Dataset Location",
27
+ description: "What is the location of the BigQuery dataset referenced in the query?",
28
+ default: "US",
29
+ input: (0, params_1.select)({
30
+ "Columbus, Ohio (us-east5)": "us-east5",
31
+ "Iowa (us-central1)": "us-central1",
32
+ "Las Vegas (us-west4)": "us-west4",
33
+ "Los Angeles (us-west2)": "us-west2",
34
+ "Montréal (northamerica-northeast1)": "northamerica-northeast1",
35
+ "Northern Virginia (us-east4)": "us-east4",
36
+ "Oregon (us-west1)": "us-west1",
37
+ "Salt Lake City (us-west3)": "us-west3",
38
+ "São Paulo (southamerica-east1)": "southamerica-east1",
39
+ "Santiago (southamerica-west1)": "southamerica-west1",
40
+ "South Carolina (us-east1)": "us-east1",
41
+ "Toronto (northamerica-northeast2)": "northamerica-northeast2",
42
+ "Delhi (asia-south2)": "asia-south2",
43
+ "Hong Kong (asia-east2)": "asia-east2",
44
+ "Jakarta (asia-southeast2)": "asia-southeast2",
45
+ "Melbourne (australia-southeast2)": "australia-southeast2",
46
+ "Mumbai (asia-south1)": "asia-south1",
47
+ "Osaka (asia-northeast2)": "asia-northeast2",
48
+ "Seoul (asia-northeast3)": "asia-northeast3",
49
+ "Singapore (asia-southeast1)": "asia-southeast1",
50
+ "Sydney (australia-southeast1)": "australia-southeast1",
51
+ "Taiwan (asia-east1)": "asia-east1",
52
+ "Tokyo (asia-northeast1)": "asia-northeast1",
53
+ "Belgium (europe-west1)": "europe-west1",
54
+ "Finland (europe-north1)": "europe-north1",
55
+ "Frankfurt (europe-west3)": "europe-west3",
56
+ "London (europe-west2)": "europe-west2",
57
+ "Madrid (europe-southwest1)": "europe-southwest1",
58
+ "Milan (europe-west8)": "europe-west8",
59
+ "Netherlands (europe-west4)": "europe-west4",
60
+ "Paris (europe-west9)": "europe-west9",
61
+ "Warsaw (europe-central2)": "europe-central2",
62
+ "Zürich (europe-west6)": "europe-west6",
63
+ "US Multi-Region (US)": "US",
64
+ "EU Mutli-Region (EU)": "EU",
65
+ }),
66
+ }),
67
+ transferConfigName: (0, params_1.defineString)("TRANSFER_CONFIG_NAME", { default: "" }),
68
+ datasetId: (0, params_1.defineString)("DATASET_ID", {
69
+ label: "Dataset ID",
70
+ description: "What's the BigQuery destination dataset you'd like to use? Each transfer run will write to a table in this destination dataset.",
71
+ input: {
72
+ text: {
73
+ nonEmpty: true,
74
+ example: "customer_data",
75
+ },
76
+ },
77
+ }),
78
+ tableName: (0, params_1.defineString)("TABLE_NAME", {
79
+ label: "Destination Table Name",
80
+ description: "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.",
81
+ input: {
82
+ text: {
83
+ nonEmpty: true,
84
+ example: "transactions",
85
+ },
86
+ },
87
+ }),
88
+ queryString: (0, params_1.defineString)("QUERY_STRING", {
89
+ label: "Query String",
90
+ description: "What's the BQ query you'd like to execute?",
91
+ input: {
92
+ text: {
93
+ nonEmpty: true,
94
+ example: "SELECT * from <PROJECT_ID>.customer_data.transactions",
95
+ },
96
+ },
97
+ }),
98
+ displayName: (0, params_1.defineString)("DISPLAY_NAME", {
99
+ label: "Display Name",
100
+ description: "What display name would you like to use?",
101
+ input: {
102
+ text: {
103
+ nonEmpty: true,
104
+ example: "Daily Rollup - Customer Transactions",
105
+ },
106
+ },
107
+ }),
108
+ partitioningField: (0, params_1.defineString)("PARTITIONING_FIELD", {
109
+ label: "Partitioning Field",
110
+ description: "What's the partitioning field on the destination table ID? Leave empty if not using a partitioning field.",
111
+ default: "",
112
+ input: { text: { example: "timestamp" } },
113
+ }),
114
+ schedule: (0, params_1.defineString)("SCHEDULE", {
115
+ label: "Schedule",
116
+ description: "What's the execution schedule you'd like to use for this query?",
117
+ input: {
118
+ text: {
119
+ nonEmpty: true,
120
+ example: "every 15 minutes",
121
+ },
122
+ },
123
+ }),
124
+ firestoreCollection: (0, params_1.defineString)("COLLECTION_PATH", {
125
+ label: "Firestore Collection",
126
+ description: "What's the top-level Firestore Collection to store transfer configs, run metadata, and query output?",
127
+ default: "transferConfigs",
128
+ input: {
129
+ text: {
130
+ example: "transferConfigs",
131
+ validationRegex: /^[^\/]+(\/[^\/]+\/[^\/]+)*$/,
132
+ validationErrorMessage: "Must be a valid Cloud Firestore Collection",
133
+ },
134
+ },
135
+ }),
136
+ logLevel: (0, params_1.defineString)("LOG_LEVEL", {
137
+ label: "Log Level",
138
+ description: "What's the log level you'd like to use for this extension?",
139
+ default: "info",
140
+ input: (0, params_1.select)({
141
+ DEBUG: "debug",
142
+ INFO: "info",
143
+ WARN: "warn",
144
+ ERROR: "error",
145
+ SILENT: "silent",
146
+ }),
147
+ }),
148
+ };
149
+ exports.CONFIG_EXPRESSIONS = {
150
+ pubSubTopic: (0, params_1.expr) `kit-${instanceId}-processMessages`,
151
+ };
152
+ function optional(value) {
153
+ const normalized = value.trim();
154
+ return normalized.length > 0 ? normalized : undefined;
155
+ }
156
+ function normalizeLogLevel(value) {
157
+ const normalized = value.toLowerCase();
158
+ return LOG_LEVEL_OPTIONS.includes(normalized)
159
+ ? normalized
160
+ : "info";
161
+ }
162
+ /** Reads runtime values from Firebase deploy-time parameters. */
163
+ function configFromEnv() {
164
+ const resolvedInstanceId = params.instanceId.value();
165
+ return {
166
+ bigqueryDatasetLocation: params.bigqueryDatasetLocation.value(),
167
+ projectId: params_1.projectID.value(),
168
+ instanceId: resolvedInstanceId,
169
+ transferConfigName: optional(params.transferConfigName.value()),
170
+ datasetId: params.datasetId.value(),
171
+ tableName: params.tableName.value(),
172
+ queryString: params.queryString.value(),
173
+ displayName: params.displayName.value(),
174
+ partitioningField: optional(params.partitioningField.value()),
175
+ schedule: params.schedule.value(),
176
+ pubSubTopic: `kit-${resolvedInstanceId}-processMessages`,
177
+ firestoreCollection: params.firestoreCollection.value(),
178
+ logLevel: normalizeLogLevel(params.logLevel.value()),
179
+ };
180
+ }
181
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/lib/dts.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ import * as bigqueryDataTransfer from "@google-cloud/bigquery-data-transfer";
2
+ import type { ResolvedBigqueryFirestoreExportConfig } from "./export-config";
3
+ export type DataTransferClient = bigqueryDataTransfer.v1.DataTransferServiceClient;
4
+ export type TransferConfig = bigqueryDataTransfer.protos.google.cloud.bigquery.datatransfer.v1.ITransferConfig;
5
+ export declare const PARTITIONING_FIELD_REMOVAL_ERROR_PREFIX = "Cannot remove partitioning_field from an existing transfer config";
6
+ export declare const PARTITIONING_FIELD_REMOVAL_ERROR = "Cannot remove partitioning_field from an existing transfer config. The BigQuery Data Transfer API does not support clearing this parameter once it has been set. To change partitioning, create a new transfer config with the desired setting.";
7
+ /**
8
+ * Creates the protobuf-shaped request used for a scheduled query.
9
+ *
10
+ * The query runs as whichever identity creates it, which is this function. To
11
+ * name a different account, `serviceAccountName` goes on the request rather
12
+ * than on the transfer config, and the caller needs `actAs` on the account it
13
+ * names, including its own.
14
+ */
15
+ export declare function createTransferConfigRequest(config: ResolvedBigqueryFirestoreExportConfig): bigqueryDataTransfer.protos.google.cloud.bigquery.datatransfer.v1.ICreateTransferConfigRequest;
16
+ export declare function getTransferConfig(client: DataTransferClient, transferConfigName: string): Promise<TransferConfig | null>;
17
+ export declare function createTransferConfig(client: DataTransferClient, config: ResolvedBigqueryFirestoreExportConfig): Promise<TransferConfig>;
18
+ /** Builds a minimal update mask while retaining unsupported immutable fields. */
19
+ export declare function constructUpdateTransferConfigRequest(client: DataTransferClient, transferConfigName: string, config: ResolvedBigqueryFirestoreExportConfig): Promise<bigqueryDataTransfer.protos.google.cloud.bigquery.datatransfer.v1.IUpdateTransferConfigRequest>;
20
+ export declare function updateTransferConfig(client: DataTransferClient, transferConfigName: string, config: ResolvedBigqueryFirestoreExportConfig): Promise<TransferConfig>;
21
+ //# sourceMappingURL=dts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dts.d.ts","sourceRoot":"","sources":["../src/dts.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,oBAAoB,MAAM,sCAAsC,CAAC;AAC7E,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,iBAAiB,CAAC;AAG7E,MAAM,MAAM,kBAAkB,GAC5B,oBAAoB,CAAC,EAAE,CAAC,yBAAyB,CAAC;AACpD,MAAM,MAAM,cAAc,GACxB,oBAAoB,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,eAAe,CAAC;AAMpF,eAAO,MAAM,uCAAuC,sEACxB,CAAC;AAC7B,eAAO,MAAM,gCAAgC,oPAAgN,CAAC;AAoC9P;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,qCAAqC,GAC5C,oBAAoB,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,4BAA4B,CAqBhG;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,kBAAkB,EAC1B,kBAAkB,EAAE,MAAM,GACzB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAchC;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,qCAAqC,GAC5C,OAAO,CAAC,cAAc,CAAC,CAUzB;AAED,iFAAiF;AACjF,wBAAsB,oCAAoC,CACxD,MAAM,EAAE,kBAAkB,EAC1B,kBAAkB,EAAE,MAAM,EAC1B,MAAM,EAAE,qCAAqC,GAC5C,OAAO,CAAC,oBAAoB,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,4BAA4B,CAAC,CAyDzG;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,kBAAkB,EAC1B,kBAAkB,EAAE,MAAM,EAC1B,MAAM,EAAE,qCAAqC,GAC5C,OAAO,CAAC,cAAc,CAAC,CAczB"}