@google-cloud/nodejs-common 1.9.0 → 1.9.2-alpha
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/bin/install_functions.sh +2 -1
- package/package.json +2 -2
- package/src/apis/ads_data_hub.js +5 -3
- package/src/apis/base/auth_restful_api.js +14 -2
- package/src/apis/base/restful_api_base.js +9 -6
- package/src/apis/cloud/google_cloud_api.js +79 -0
- package/src/apis/dfa_reporting.js +4 -4
- package/src/apis/sendgrid.js +2 -2
- package/src/components/firestore/access_base.js +42 -0
- package/src/components/firestore/data_access_object.js +11 -8
- package/src/components/firestore/datastore_mode_access.js +8 -3
- package/src/components/firestore/firestore_api.js +89 -0
- package/src/components/firestore/native_mode_access.js +6 -4
package/bin/install_functions.sh
CHANGED
|
@@ -1933,7 +1933,8 @@ check_firestore_existence() {
|
|
|
1933
1933
|
local firestore mode appRegion
|
|
1934
1934
|
mode="${1}"
|
|
1935
1935
|
appRegion="${2}"
|
|
1936
|
-
firestore=$(gcloud firestore databases list
|
|
1936
|
+
firestore=$(gcloud firestore databases list \
|
|
1937
|
+
--filter="name:(default)" --format="csv[no-heading](type)")
|
|
1937
1938
|
if [[ -z "${firestore}" ]]; then
|
|
1938
1939
|
printf '%s\n' "Firestore is not ready. Creating a new Firestore database\
|
|
1939
1940
|
is an irreversible operation, so read carefully before continue:"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@google-cloud/nodejs-common",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.2-alpha",
|
|
4
4
|
"description": "A NodeJs common library for solutions based on Cloud Functions",
|
|
5
5
|
"author": "Google Inc.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"@google-cloud/aiplatform": "^3.0.0",
|
|
20
20
|
"@google-cloud/automl": "^4.0.0",
|
|
21
21
|
"@google-cloud/bigquery": "^7.2.0",
|
|
22
|
-
"@google-cloud/datastore": "^8.
|
|
22
|
+
"@google-cloud/datastore": "^8.2.2",
|
|
23
23
|
"@google-cloud/firestore": "^6.7.0",
|
|
24
24
|
"@google-cloud/logging-winston": "^6.0.0",
|
|
25
25
|
"@google-cloud/pubsub": "^4.0.2",
|
package/src/apis/ads_data_hub.js
CHANGED
|
@@ -108,7 +108,9 @@ class AdsDataHub extends AuthRestfulApi {
|
|
|
108
108
|
* to the specified BigQuery destination table. The returned operation name
|
|
109
109
|
* can be used to poll for query completion status.
|
|
110
110
|
* @see https://developers.google.com/ads-data-hub/reference/rest/v1/customers.analysisQueries/startTransient
|
|
111
|
-
* @param {
|
|
111
|
+
* @param {!AnalysisQuery} query An analysis query that can be executed within
|
|
112
|
+
* Ads Data Hub. Its properties include 'queryText', 'parameterTypes', etc.
|
|
113
|
+
* @see https://developers.google.com/ads-data-hub/reference/rest/v1/customers.analysisQueries#AnalysisQuery
|
|
112
114
|
* @param {Object} spec Defines the query execution parameters.
|
|
113
115
|
* @see https://developers.google.com/ads-data-hub/reference/rest/v1/QueryExecutionSpec
|
|
114
116
|
* @param {string} destTable Destination BigQuery table for query results with
|
|
@@ -121,9 +123,9 @@ class AdsDataHub extends AuthRestfulApi {
|
|
|
121
123
|
* @return {!Promise<Object>} Promised operation object.
|
|
122
124
|
* @see https://developers.google.com/ads-data-hub/reference/rest/v1/operations#Operation
|
|
123
125
|
*/
|
|
124
|
-
async startTransientQuery(
|
|
126
|
+
async startTransientQuery(query, spec, destTable, customerId = this.customerId) {
|
|
125
127
|
const path = `customers/${customerId}/analysisQueries:startTransient`;
|
|
126
|
-
const data = { query
|
|
128
|
+
const data = { query, spec, destTable };
|
|
127
129
|
const response = await this.request(path, 'POST', data);
|
|
128
130
|
return response.data;
|
|
129
131
|
}
|
|
@@ -16,13 +16,25 @@
|
|
|
16
16
|
* @fileoverview A base class for RESTful API with authorization client.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
const {
|
|
19
|
+
const { RestfulApiBase } = require('./restful_api_base');
|
|
20
20
|
const AuthClient = require('../auth_client.js');
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* A RESTful API class with authorization client.
|
|
24
24
|
*/
|
|
25
|
-
class AuthRestfulApi extends
|
|
25
|
+
class AuthRestfulApi extends RestfulApiBase {
|
|
26
|
+
|
|
27
|
+
constructor(env = process.env, options = {}) {
|
|
28
|
+
super(env);
|
|
29
|
+
/**
|
|
30
|
+
* `authClient` can be consumed by cloud client library as the auth
|
|
31
|
+
* client. By passing this in, we can offer more flexible auth clients in
|
|
32
|
+
* test cases for API client library and cloud client library in future.
|
|
33
|
+
*/
|
|
34
|
+
if (options.authClient) {
|
|
35
|
+
this.auth = options.authClient;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
26
38
|
|
|
27
39
|
/**
|
|
28
40
|
* Returns the Api scope for authorization.
|
|
@@ -22,6 +22,8 @@ const {
|
|
|
22
22
|
GaxiosOptions,
|
|
23
23
|
} = require('gaxios');
|
|
24
24
|
|
|
25
|
+
const { getLogger } = require('../../components/utils.js');
|
|
26
|
+
|
|
25
27
|
/**
|
|
26
28
|
* A type for an Api response which is independent to the 'request' library.
|
|
27
29
|
* @typedef {{
|
|
@@ -35,10 +37,11 @@ let Response;
|
|
|
35
37
|
* Base class for RESTful API based on gaxios.
|
|
36
38
|
* @see https://github.com/googleapis/gaxios
|
|
37
39
|
*/
|
|
38
|
-
class
|
|
40
|
+
class RestfulApiBase {
|
|
39
41
|
|
|
40
42
|
constructor(env = process.env) {
|
|
41
43
|
this.env = env;
|
|
44
|
+
this.logger = getLogger(this.constructor.name);
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
/**
|
|
@@ -46,7 +49,7 @@ class RestfuleApiBase {
|
|
|
46
49
|
* @return {string}
|
|
47
50
|
* @abstract
|
|
48
51
|
*/
|
|
49
|
-
getBaseUrl() { }
|
|
52
|
+
async getBaseUrl() { }
|
|
50
53
|
|
|
51
54
|
/**
|
|
52
55
|
* Returns default HTTP headers.
|
|
@@ -93,7 +96,7 @@ class RestfuleApiBase {
|
|
|
93
96
|
const options = Object.assign(
|
|
94
97
|
this.getRequesterOptions(),
|
|
95
98
|
{
|
|
96
|
-
url: this.getRequestUrl(uri),
|
|
99
|
+
url: await this.getRequestUrl(uri),
|
|
97
100
|
method,
|
|
98
101
|
headers: headers || await this.getDefaultHeaders(),
|
|
99
102
|
data,
|
|
@@ -111,8 +114,8 @@ class RestfuleApiBase {
|
|
|
111
114
|
* @param {string} requestUri The URI of the specific resource to request.
|
|
112
115
|
* @return {string} representing the fully-qualified API URL.
|
|
113
116
|
*/
|
|
114
|
-
getRequestUrl(requestUri) {
|
|
115
|
-
const baseUrl = this.getBaseUrl();
|
|
117
|
+
async getRequestUrl(requestUri) {
|
|
118
|
+
const baseUrl = await this.getBaseUrl();
|
|
116
119
|
if (requestUri) {
|
|
117
120
|
if (requestUri.toLocaleLowerCase().startsWith('http')) return requestUri;
|
|
118
121
|
return `${baseUrl}/${requestUri}`;
|
|
@@ -139,5 +142,5 @@ class RestfuleApiBase {
|
|
|
139
142
|
|
|
140
143
|
module.exports = {
|
|
141
144
|
Response,
|
|
142
|
-
|
|
145
|
+
RestfulApiBase,
|
|
143
146
|
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// Copyright 2023 Google Inc.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @fileoverview The base class of Google Cloud Apis.
|
|
17
|
+
*/
|
|
18
|
+
const AuthClient = require('../auth_client.js');
|
|
19
|
+
const { AuthRestfulApi } = require('../base/auth_restful_api.js');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A RESTful API class for Google Cloud Platform API with ADC as the
|
|
23
|
+
* authorization method.
|
|
24
|
+
*/
|
|
25
|
+
class GoogleCloudApi extends AuthRestfulApi {
|
|
26
|
+
|
|
27
|
+
constructor(env = process.env, options = {}) {
|
|
28
|
+
super(env, options);
|
|
29
|
+
this.projectId = options.projectId || env['GCP_PROJECT'];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** @override */
|
|
33
|
+
getScope() {
|
|
34
|
+
return ['https://www.googleapis.com/auth/cloud-platform'];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @override
|
|
39
|
+
* Returns the `GoogleAuth` object for a Google Cloud component object.
|
|
40
|
+
* If the component is based on Google Cloud Client Library, it will use the
|
|
41
|
+
* `ADC` auth object by itself. However, some components are based on Google
|
|
42
|
+
* API Client Library, which is based on API Scope and an explicit auth
|
|
43
|
+
* object. In this situation, this function can help to generate such an auth
|
|
44
|
+
* object.
|
|
45
|
+
* By default, `AuthClient` (getDefaultAuth()) will return an auth client
|
|
46
|
+
* based on the settings in ENV while the OAuth is the most preferred.
|
|
47
|
+
* This works for most of the external API clients (in the '../apis'
|
|
48
|
+
* folder), however this won't work in the Cloud Functions, as those OAuth
|
|
49
|
+
* token usually won't have enough permission to invoke Google Cloud API.
|
|
50
|
+
* Using the method `getApplicationDefaultCredentials` to force
|
|
51
|
+
* `AuthClient` return an ADC auth client, which will work in the Cloud.
|
|
52
|
+
*/
|
|
53
|
+
async getAuth() {
|
|
54
|
+
if (this.auth) return this.auth;
|
|
55
|
+
this.authClient = new AuthClient(this.getScope(), this.env);
|
|
56
|
+
// Not required for ADC: await this.authClient.prepareCredentials();
|
|
57
|
+
this.auth = this.authClient.getApplicationDefaultCredentials();
|
|
58
|
+
return this.auth;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Gets the GCP project Id. In Cloud Functions, it *should* be passed in
|
|
63
|
+
* through environment variable during the deployment. But if it doesn't exist
|
|
64
|
+
* (for example, in local unit tests), this function will fallback to ADC
|
|
65
|
+
* (Application Default Credential) auth's asynchronous function to get the
|
|
66
|
+
* project Id.
|
|
67
|
+
* @return {string}
|
|
68
|
+
*/
|
|
69
|
+
async getProjectId() {
|
|
70
|
+
if (!this.projectId) {
|
|
71
|
+
const auth = await this.getAuth();
|
|
72
|
+
this.projectId = await auth.getProjectId();
|
|
73
|
+
}
|
|
74
|
+
return this.projectId;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
module.exports = { GoogleCloudApi };
|
|
@@ -391,18 +391,18 @@ class DfaReporting {
|
|
|
391
391
|
throw new Error(`Unsupported report status: ${data.status}`);
|
|
392
392
|
}
|
|
393
393
|
|
|
394
|
-
//TODO(lushu) check the response for very big file.
|
|
395
394
|
/**
|
|
396
|
-
*
|
|
395
|
+
* Gets the stream of the report file.
|
|
397
396
|
* @param {string} url
|
|
398
|
-
* @return {!Promise<
|
|
397
|
+
* @return {!Promise<stream>}
|
|
399
398
|
*/
|
|
400
|
-
async
|
|
399
|
+
async getReportFileStream(url) {
|
|
401
400
|
const auth = await this.getAuth_();
|
|
402
401
|
const headers = await auth.getRequestHeaders();
|
|
403
402
|
const response = await request({
|
|
404
403
|
method: 'GET',
|
|
405
404
|
headers,
|
|
405
|
+
responseType: 'stream',
|
|
406
406
|
url,
|
|
407
407
|
});
|
|
408
408
|
return response.data;
|
package/src/apis/sendgrid.js
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
'use strict';
|
|
20
20
|
|
|
21
|
-
const {
|
|
21
|
+
const { RestfulApiBase } = require('./base/restful_api_base.js');
|
|
22
22
|
const { getLogger } = require('../components/utils.js');
|
|
23
23
|
|
|
24
24
|
const API_VERSION = 'v3';
|
|
@@ -28,7 +28,7 @@ const API_ENDPOINT = 'https://api.sendgrid.com';
|
|
|
28
28
|
* SendGrid API access class.
|
|
29
29
|
* @see https://docs.sendgrid.com/api-reference/how-to-use-the-sendgrid-v3-api/authentication
|
|
30
30
|
*/
|
|
31
|
-
class SendGrid extends
|
|
31
|
+
class SendGrid extends RestfulApiBase {
|
|
32
32
|
|
|
33
33
|
constructor(apiKey, env = process.env) {
|
|
34
34
|
super(env);
|
|
@@ -27,6 +27,10 @@ const {
|
|
|
27
27
|
DocumentData,
|
|
28
28
|
Transaction: NativeModeTransaction,
|
|
29
29
|
} = require('@google-cloud/firestore');
|
|
30
|
+
const {
|
|
31
|
+
FirestoreApi,
|
|
32
|
+
DEFAULT_DATABASE,
|
|
33
|
+
} = require('./firestore_api.js');
|
|
30
34
|
|
|
31
35
|
/**
|
|
32
36
|
* Document in Native mode or Entity in Datastore mode.
|
|
@@ -122,6 +126,17 @@ const DataSource = Object.freeze({
|
|
|
122
126
|
DATASTORE: 'datastore',
|
|
123
127
|
});
|
|
124
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Definition of a database. Currently, it supports:
|
|
131
|
+
* 1. Firestore Native mode
|
|
132
|
+
* 2. Firestore Datastore mode
|
|
133
|
+
* @typedef {(
|
|
134
|
+
* source: !DataSource,
|
|
135
|
+
* id: string,
|
|
136
|
+
* )}
|
|
137
|
+
*/
|
|
138
|
+
let Database;
|
|
139
|
+
|
|
125
140
|
/**
|
|
126
141
|
* Firestore has two modes: 'Native' and 'Datastore'. Only one of them can be
|
|
127
142
|
* set in a Cloud Project and it can not be changed in the Cloud Project once
|
|
@@ -216,10 +231,33 @@ class FirestoreAccessBase {
|
|
|
216
231
|
|
|
217
232
|
}
|
|
218
233
|
|
|
234
|
+
/**
|
|
235
|
+
* Returns whether the mode of Firestore is 'Native'.
|
|
236
|
+
* @param {string} projectId GCP project Id.
|
|
237
|
+
* @param {string=} databaseId GCP project Id.
|
|
238
|
+
* @return {!Promise<!Database>}
|
|
239
|
+
*/
|
|
240
|
+
async function getFirestoreDatabase(projectId, databaseId = DEFAULT_DATABASE) {
|
|
241
|
+
try {
|
|
242
|
+
const firestore = new FirestoreApi(process.env, { projectId, databaseId });
|
|
243
|
+
const type = await firestore.getFirestoreMode();
|
|
244
|
+
console.log(`Get Firestore ${databaseId}@${projectId}, mode: ${type}`);
|
|
245
|
+
return {
|
|
246
|
+
source: DataSource[type],
|
|
247
|
+
id: firestore.databaseId,
|
|
248
|
+
};
|
|
249
|
+
} catch (error) {
|
|
250
|
+
console.error(`Failed to get Firestore ${databaseId}@${projectId}: `,
|
|
251
|
+
error.message);
|
|
252
|
+
throw error;
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
|
|
219
256
|
/**
|
|
220
257
|
* Returns whether the mode of Firestore is 'Native'.
|
|
221
258
|
* @param {string=} projectId GCP project Id.
|
|
222
259
|
* @return {!Promise<boolean>}
|
|
260
|
+
* @deprecated
|
|
223
261
|
*/
|
|
224
262
|
async function isNativeMode(projectId = process.env['GCP_PROJECT']) {
|
|
225
263
|
try {
|
|
@@ -237,8 +275,12 @@ module.exports = {
|
|
|
237
275
|
Transaction,
|
|
238
276
|
Filter,
|
|
239
277
|
TransactionOperation,
|
|
278
|
+
Database,
|
|
240
279
|
DatastoreDocumentFacade,
|
|
241
280
|
DatastoreTransactionFacade,
|
|
242
281
|
FirestoreAccessBase,
|
|
282
|
+
getFirestoreDatabase,
|
|
283
|
+
DEFAULT_DATABASE,
|
|
284
|
+
FirestoreApi,
|
|
243
285
|
isNativeMode,
|
|
244
286
|
};
|
|
@@ -25,6 +25,8 @@ const {
|
|
|
25
25
|
Filter,
|
|
26
26
|
TemplatedTxFunction,
|
|
27
27
|
FirestoreAccessBase,
|
|
28
|
+
Database,
|
|
29
|
+
DEFAULT_DATABASE,
|
|
28
30
|
} = require('./access_base.js');
|
|
29
31
|
const NativeModeAccess = require('./native_mode_access.js');
|
|
30
32
|
const DatastoreModeAccess = require('./datastore_mode_access.js');
|
|
@@ -33,8 +35,7 @@ const DatastoreModeAccess = require('./datastore_mode_access.js');
|
|
|
33
35
|
* This is data access object base class on Firestore. It seals the details of
|
|
34
36
|
* different underlying databases, Firestore and Datastore.
|
|
35
37
|
* This class relies on an initial parameter in construtor to indicate the
|
|
36
|
-
* Firestore type.
|
|
37
|
-
* environment variable named 'FIRESTORE_TYPE'.
|
|
38
|
+
* Firestore type.
|
|
38
39
|
*
|
|
39
40
|
* Firestore and Datastore have different transaction APIs. In that case,
|
|
40
41
|
* separate DAOs are required to offer different functions in each mode.
|
|
@@ -45,22 +46,24 @@ class DataAccessObject {
|
|
|
45
46
|
* Initializes the instance based on given data source.
|
|
46
47
|
* @param {string} kind The data model name.
|
|
47
48
|
* @param {string} namespace The namespace of the data.
|
|
48
|
-
* @param {!DataSource}
|
|
49
|
+
* @param {!Database|!DataSource} database The database or data base type.
|
|
49
50
|
* @param {string} projectId The Id of Cloud project.
|
|
50
51
|
*/
|
|
51
|
-
constructor(kind, namespace,
|
|
52
|
-
|
|
52
|
+
constructor(kind, namespace, database,
|
|
53
|
+
projectId = process.env['GCP_PROJECT']) {
|
|
53
54
|
/** @const {string} */ this.namespace = namespace;
|
|
54
|
-
/** @const {!DataSource} */ this.dataSource =
|
|
55
|
+
/** @const {!DataSource} */ this.dataSource =
|
|
56
|
+
typeof database === 'string' ? database : database.source;
|
|
57
|
+
const databaseId = database.id || DEFAULT_DATABASE;
|
|
55
58
|
/** @type {!FirestoreAccessBase} */ this.accessObject = undefined;
|
|
56
59
|
switch (this.dataSource) {
|
|
57
60
|
case DataSource.FIRESTORE:
|
|
58
61
|
this.accessObject = new NativeModeAccess(
|
|
59
|
-
|
|
62
|
+
`${this.namespace}/database/${kind}`, projectId, databaseId);
|
|
60
63
|
break;
|
|
61
64
|
case DataSource.DATASTORE:
|
|
62
65
|
this.accessObject = new DatastoreModeAccess(this.namespace, kind,
|
|
63
|
-
|
|
66
|
+
projectId, databaseId);
|
|
64
67
|
break;
|
|
65
68
|
default:
|
|
66
69
|
throw new Error(`Unknown DataSource item: ${this.dataSource}.`);
|
|
@@ -29,6 +29,7 @@ const {
|
|
|
29
29
|
DatastoreDocumentFacade,
|
|
30
30
|
DatastoreTransactionFacade,
|
|
31
31
|
FirestoreAccessBase,
|
|
32
|
+
DEFAULT_DATABASE,
|
|
32
33
|
} = require('./access_base.js');
|
|
33
34
|
const {getLogger, wait} = require('../utils.js');
|
|
34
35
|
|
|
@@ -46,11 +47,15 @@ class DatastoreModeAccess {
|
|
|
46
47
|
* Initializes DatastoreModeAccess instance.
|
|
47
48
|
* @param {string} namespace The namespace for data.
|
|
48
49
|
* @param {string} kind The kind of this entity.
|
|
49
|
-
* @param {string} projectId The Id of Cloud project.
|
|
50
|
+
* @param {string=} projectId The Id of Cloud project.
|
|
51
|
+
* @param {string=} databaseId The Id of Firestore database.
|
|
50
52
|
*/
|
|
51
|
-
constructor(namespace, kind, projectId = process.env['GCP_PROJECT']
|
|
53
|
+
constructor(namespace, kind, projectId = process.env['GCP_PROJECT'],
|
|
54
|
+
databaseId = process.env['DATABASE_ID'] || DEFAULT_DATABASE) {
|
|
55
|
+
// '(default)' is not allowed, use empty string '' to refer the default database.
|
|
56
|
+
const idForDatastore = databaseId === DEFAULT_DATABASE ? '' : databaseId;
|
|
52
57
|
/** @type{Datastore} */
|
|
53
|
-
this.datastore = new Datastore({projectId});
|
|
58
|
+
this.datastore = new Datastore({ projectId, databaseId: idForDatastore });
|
|
54
59
|
this.kind = kind;
|
|
55
60
|
this.namespace = namespace;
|
|
56
61
|
this.logger = getLogger('DS.ACC');
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// Copyright 2023 Google Inc.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
const { GoogleCloudApi } = require('../../apis/cloud/google_cloud_api');
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The name of default database.
|
|
19
|
+
* @see https://cloud.google.com/firestore/docs/reference/rest/v1/projects.databases#resource:-database
|
|
20
|
+
* @const {string}
|
|
21
|
+
*/
|
|
22
|
+
const DEFAULT_DATABASE = '(default)';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The modes of Firestore. Mode changes are only allowed if the database is empty.
|
|
26
|
+
* @see https://cloud.google.com/datastore/docs/firestore-or-datastore
|
|
27
|
+
* @see https://cloud.google.com/firestore/docs/reference/rest/v1/projects.databases#DatabaseType
|
|
28
|
+
* @enum {string}
|
|
29
|
+
*/
|
|
30
|
+
const FIRESTORE_MODE = Object.freeze({
|
|
31
|
+
FIRESTORE_NATIVE: 'FIRESTORE',
|
|
32
|
+
DATASTORE_MODE: 'DATASTORE',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
class FirestoreApi extends GoogleCloudApi {
|
|
36
|
+
|
|
37
|
+
constructor(env = process.env, options = {}) {
|
|
38
|
+
super(env, options);
|
|
39
|
+
this.apiUrl = 'https://firestore.googleapis.com';
|
|
40
|
+
this.version = 'v1';
|
|
41
|
+
this.databaseId = options.databaseId || env.DATABASE_ID || DEFAULT_DATABASE;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** @override */
|
|
45
|
+
async getBaseUrl() {
|
|
46
|
+
const projectId = await this.getProjectId();
|
|
47
|
+
return `${this.apiUrl}/${this.version}/projects/${projectId}`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Gets the information of the default database.
|
|
52
|
+
* If the database is ready, will return:
|
|
53
|
+
* {
|
|
54
|
+
* data: {
|
|
55
|
+
* name:...
|
|
56
|
+
* type:...
|
|
57
|
+
* },
|
|
58
|
+
* code: 200
|
|
59
|
+
* }
|
|
60
|
+
* If the database is not created, will throw an error: "Request failed with
|
|
61
|
+
* status code 404"
|
|
62
|
+
* @see https://cloud.google.com/firestore/docs/reference/rest/v1/projects.databases/get
|
|
63
|
+
* @return {Database}
|
|
64
|
+
* @see https://cloud.google.com/firestore/docs/reference/rest/v1/projects.databases#Database
|
|
65
|
+
*/
|
|
66
|
+
async getDatabase(databaseId = this.databaseId) {
|
|
67
|
+
return super.request(`databases/${databaseId}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Gets the mode of the Firestore database.
|
|
72
|
+
* @param {string=} databaseId
|
|
73
|
+
* @return {'FIRESTORE'|'DATASTORE'} Mode of the Firestore.
|
|
74
|
+
*/
|
|
75
|
+
async getFirestoreMode(databaseId = this.databaseId) {
|
|
76
|
+
const response = await this.getDatabase(databaseId);
|
|
77
|
+
if (!response.data) {
|
|
78
|
+
this.logger.error(`Fail to find database ${databaseId}`, response);
|
|
79
|
+
throw new Error(`Fail to find database ${databaseId}`);
|
|
80
|
+
}
|
|
81
|
+
this.logger.debug(`Get ${databaseId} in mode ${response.data.type}.`);
|
|
82
|
+
return FIRESTORE_MODE[response.data.type];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
module.exports = {
|
|
87
|
+
DEFAULT_DATABASE,
|
|
88
|
+
FirestoreApi,
|
|
89
|
+
};
|
|
@@ -24,7 +24,7 @@ const {
|
|
|
24
24
|
CollectionReference,
|
|
25
25
|
OrderByDirection,
|
|
26
26
|
} = require('@google-cloud/firestore');
|
|
27
|
-
const {FirestoreAccessBase} = require('./access_base.js');
|
|
27
|
+
const { FirestoreAccessBase, DEFAULT_DATABASE } = require('./access_base.js');
|
|
28
28
|
const {getLogger} = require('../utils.js');
|
|
29
29
|
|
|
30
30
|
/**
|
|
@@ -41,11 +41,13 @@ class NativeModeAccess {
|
|
|
41
41
|
* way. This constructor will check the path to make sure it presents a
|
|
42
42
|
* 'collection', otherwise an Error will be thrown.
|
|
43
43
|
* @param {string} path Path for the 'collection'.
|
|
44
|
-
* @param {string} projectId The Id of Cloud project.
|
|
44
|
+
* @param {string=} projectId The Id of Cloud project.
|
|
45
|
+
* @param {string=} databaseId The Id of Firestore database.
|
|
45
46
|
*/
|
|
46
|
-
constructor(path, projectId = process.env['GCP_PROJECT']
|
|
47
|
+
constructor(path, projectId = process.env['GCP_PROJECT'],
|
|
48
|
+
databaseId = process.env['DATABASE_ID'] || DEFAULT_DATABASE) {
|
|
47
49
|
/** @type {!Firestore} */
|
|
48
|
-
this.firestore = new Firestore({projectId});
|
|
50
|
+
this.firestore = new Firestore({ projectId, databaseId });
|
|
49
51
|
if (path.split('/').length % 2 === 0) {
|
|
50
52
|
throw new Error(`Invalid path for Collection: ${path}`);
|
|
51
53
|
}
|