@pi-r/gcp 0.9.4 → 0.10.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/client/index.js +238 -110
- package/package.json +5 -5
- package/types/index.d.ts +6 -2
- package/upload/index.js +9 -6
package/client/index.js
CHANGED
|
@@ -54,26 +54,43 @@ function getApp(credential, isDB) {
|
|
|
54
54
|
const { getStorage } = require('@firebase/storage');
|
|
55
55
|
return getStorage(app);
|
|
56
56
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
const adminApp = require('firebase-admin/app');
|
|
58
|
+
const clientApp = (0, types_1.isString)(credential.admin) || (0, types_1.isPlainObject)(credential.admin);
|
|
59
|
+
let app;
|
|
60
|
+
if (!clientApp) {
|
|
61
|
+
for (const item of adminApp.getApps()) {
|
|
61
62
|
if (!isDB && storageBucket && item.name === storageBucket || isDB && databaseURL && item.name === databaseURL) {
|
|
62
63
|
app = item;
|
|
63
64
|
break;
|
|
64
65
|
}
|
|
65
66
|
}
|
|
66
|
-
if (!app) {
|
|
67
|
-
app = isDB ? ADMIN_DB[databaseURL || "[DEFAULT]"] ||= initializeApp({ credential: applicationDefault(), databaseURL }, databaseURL) : ADMIN_STORAGE[storageBucket || "[DEFAULT]"] ||= initializeApp({ credential: applicationDefault(), storageBucket }, storageBucket);
|
|
68
|
-
}
|
|
69
67
|
credential.admin = true;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
}
|
|
69
|
+
if (!app) {
|
|
70
|
+
let key = (isDB ? databaseURL : storageBucket) || "[DEFAULT]";
|
|
71
|
+
if (clientApp) {
|
|
72
|
+
key += JSON.stringify(credential.admin);
|
|
73
|
+
}
|
|
74
|
+
app = isDB ? ADMIN_DB[key] : ADMIN_STORAGE[key];
|
|
75
|
+
if (!app) {
|
|
76
|
+
let lib, credentialApp;
|
|
77
|
+
if (clientApp) {
|
|
78
|
+
lib = require('firebase-admin');
|
|
79
|
+
credentialApp = adminApp.cert(credential.admin);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
lib = adminApp;
|
|
83
|
+
credentialApp = adminApp.applicationDefault();
|
|
84
|
+
}
|
|
85
|
+
app = isDB ? ADMIN_DB[key] = lib.initializeApp({ credential: credentialApp, databaseURL }, key) : ADMIN_STORAGE[key] = lib.initializeApp({ credential: credentialApp, storageBucket }, key);
|
|
73
86
|
}
|
|
74
|
-
const { getStorage } = require('firebase-admin/storage');
|
|
75
|
-
return getStorage(app);
|
|
76
87
|
}
|
|
88
|
+
if (isDB) {
|
|
89
|
+
const { getDatabase } = require('firebase-admin/database');
|
|
90
|
+
return getDatabase(app);
|
|
91
|
+
}
|
|
92
|
+
const { getStorage } = require('firebase-admin/storage');
|
|
93
|
+
return getStorage(app);
|
|
77
94
|
}
|
|
78
95
|
async function hasBucket(client) {
|
|
79
96
|
const [exists] = await client.exists().catch((err) => isErrorConflict(err) ? [true] : [false]);
|
|
@@ -121,10 +138,15 @@ async function updatePredefinedAcl(acl, values, metadata = {}) {
|
|
|
121
138
|
async function setUniformBucketLevel(bucket, enabled) {
|
|
122
139
|
return bucket.setMetadata({ iamConfiguration: { uniformBucketLevelAccess: { enabled } } });
|
|
123
140
|
}
|
|
141
|
+
const keyLimit = (limit) => limit > 0 ? `_${limit}` : '_0';
|
|
124
142
|
const asFieldPath = (params) => Array.isArray(params) && params.every(item => typeof item === 'string') ? new firestore_1.FieldPath(...params) : params;
|
|
125
|
-
const getFirebasePackageName = (credential) => credential.apiKey && credential.authDomain ? 'firebase' : 'firebase-admin';
|
|
126
|
-
const isErrorConflict = (err) =>
|
|
143
|
+
const getFirebasePackageName = (credential) => credential.apiKey && credential.authDomain && credential ? 'firebase' : 'firebase-admin';
|
|
144
|
+
const isErrorConflict = (err) => err instanceof Error && err.code === 409;
|
|
127
145
|
const hasGoogleAuth = (credential) => (0, types_1.isString)(credential.keyFilename || credential.keyFile || process.env.GOOGLE_APPLICATION_CREDENTIALS) || (0, types_1.isObject)(credential.credentials) || !!credential.authClient;
|
|
146
|
+
const isSpanner = (data) => data.product === "spanner" || !data.product && !!(data.name && data.database && (data.query || data.table));
|
|
147
|
+
const isBigtable = (data) => data.product === "bigtable" || !data.product && !!(data.name && data.table && !data.database);
|
|
148
|
+
const isBigQuery = (data) => data.product === "bigquery" || !data.product && !!(!data.name && data.table && data.database || (0, types_1.isString)(data.query) || (0, types_1.isString)(data.options?.query));
|
|
149
|
+
const isDatastore = (data) => data.product === "datastore" || !data.product && !!(data.keys || data.kind || data.query && !data.table && !data.id);
|
|
128
150
|
function isFirebaseApp(credential, store, admin) {
|
|
129
151
|
return !!(credential.apiKey && credential.authDomain && (store || credential.databaseURL) || credential.product === "firebase" && process.env.GOOGLE_APPLICATION_CREDENTIALS) && (!admin || !credential.admin);
|
|
130
152
|
}
|
|
@@ -136,12 +158,11 @@ function validateDatabase(credential, data) {
|
|
|
136
158
|
}
|
|
137
159
|
function createStorageClient(credential, bucket) {
|
|
138
160
|
if (isFirebaseApp(credential, true)) {
|
|
139
|
-
|
|
161
|
+
const packageName = getFirebasePackageName(credential);
|
|
140
162
|
try {
|
|
141
163
|
if (bucket) {
|
|
142
164
|
credential.storageBucket = bucket;
|
|
143
165
|
}
|
|
144
|
-
packageName = getFirebasePackageName(credential);
|
|
145
166
|
return getApp(credential, false);
|
|
146
167
|
}
|
|
147
168
|
catch (err) {
|
|
@@ -153,7 +174,7 @@ function createStorageClient(credential, bucket) {
|
|
|
153
174
|
return new storage_1.Storage(credential);
|
|
154
175
|
}
|
|
155
176
|
function createDatabaseClient(credential, data) {
|
|
156
|
-
let packageName
|
|
177
|
+
let packageName;
|
|
157
178
|
try {
|
|
158
179
|
if (data?.product === "firebase" || isFirebaseApp(credential)) {
|
|
159
180
|
packageName = getFirebasePackageName(credential);
|
|
@@ -161,20 +182,19 @@ function createDatabaseClient(credential, data) {
|
|
|
161
182
|
}
|
|
162
183
|
getProjectId(credential, true);
|
|
163
184
|
if (data) {
|
|
164
|
-
|
|
165
|
-
if (product === "spanner" || !product && name && database && (query || table)) {
|
|
185
|
+
if (isSpanner(data)) {
|
|
166
186
|
const { Spanner } = require(packageName = '@google-cloud/spanner');
|
|
167
187
|
return new Spanner(credential);
|
|
168
188
|
}
|
|
169
|
-
if (
|
|
170
|
-
const { BigQuery } = require(packageName = '@google-cloud/bigquery');
|
|
171
|
-
return new BigQuery(credential);
|
|
172
|
-
}
|
|
173
|
-
if (product === "bigtable" || !product && name && table && !database) {
|
|
189
|
+
if (isBigtable(data)) {
|
|
174
190
|
const { Bigtable } = require(packageName = '@google-cloud/bigtable');
|
|
175
191
|
return new Bigtable(credential);
|
|
176
192
|
}
|
|
177
|
-
if (
|
|
193
|
+
if (isBigQuery(data)) {
|
|
194
|
+
const { BigQuery } = require(packageName = '@google-cloud/bigquery');
|
|
195
|
+
return new BigQuery(credential);
|
|
196
|
+
}
|
|
197
|
+
if (isDatastore(data)) {
|
|
178
198
|
const { Datastore } = require(packageName = '@google-cloud/datastore');
|
|
179
199
|
return new Datastore(credential);
|
|
180
200
|
}
|
|
@@ -413,14 +433,12 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
413
433
|
const clients = {};
|
|
414
434
|
const caching = length > 0 && this.hasCache(batch[0].service, sessionKey);
|
|
415
435
|
const cacheValue = { value: this.valueOfKey(credential, 'cache'), sessionKey };
|
|
416
|
-
const authItems = [];
|
|
417
436
|
const createClient = (data, type) => {
|
|
418
437
|
const client = clients[type];
|
|
419
438
|
if (client) {
|
|
420
439
|
return client;
|
|
421
440
|
}
|
|
422
441
|
const item = length === 1 ? credential : { ...credential };
|
|
423
|
-
authItems.push(item);
|
|
424
442
|
return (clients[type] = createDatabaseClient.call(this, item, data));
|
|
425
443
|
};
|
|
426
444
|
const closeClient = () => {
|
|
@@ -454,7 +472,7 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
454
472
|
};
|
|
455
473
|
for (let i = 0; i < length; ++i) {
|
|
456
474
|
const item = batch[i];
|
|
457
|
-
const { service, product, name, database, table, id, query, limit = 0, update, ignoreCache } = item;
|
|
475
|
+
const { service, product, name, database, table, id, query, limit = 0, flags = 0, update, ignoreCache } = item;
|
|
458
476
|
const useCache = caching && ignoreCache !== true;
|
|
459
477
|
cacheValue.exclusiveOf = Array.isArray(ignoreCache) ? ignoreCache : undefined;
|
|
460
478
|
let rows, queryString = '';
|
|
@@ -514,7 +532,7 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
514
532
|
rows = [group && (0, types_1.isObject)(val) && (0, types_1.isObject)(val[group[0]]) ? val[group[0]] : val];
|
|
515
533
|
}
|
|
516
534
|
}
|
|
517
|
-
else if (
|
|
535
|
+
else if (isSpanner(item)) {
|
|
518
536
|
const columns = (0, types_1.isPlainObject)(query) && query.columns || item.columns;
|
|
519
537
|
if (!(query || table && columns)) {
|
|
520
538
|
closeClient();
|
|
@@ -526,7 +544,7 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
526
544
|
}
|
|
527
545
|
const { updateType, options = {} } = item;
|
|
528
546
|
if (useCache) {
|
|
529
|
-
queryString = name + '_' + database + (table ? '_' + table + (columns ? Cloud.asString(columns, true) : '') : '') + '_' + Cloud.asString(query, true) + (limit
|
|
547
|
+
queryString = name + '_' + database + (table ? '_' + table + (columns ? Cloud.asString(columns, true) : '') : '') + '_' + Cloud.asString(query, true) + keyLimit(limit);
|
|
530
548
|
if (!update && (rows = this.getCacheResult(service, credential, queryString, cacheValue, ignoreCache))) {
|
|
531
549
|
result[i] = rows;
|
|
532
550
|
continue;
|
|
@@ -539,7 +557,7 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
539
557
|
}
|
|
540
558
|
const request = (0, types_1.isPlainObject)(query) ? query : {};
|
|
541
559
|
request.json = true;
|
|
542
|
-
if (
|
|
560
|
+
if (columns) {
|
|
543
561
|
request.columns = columns;
|
|
544
562
|
}
|
|
545
563
|
request.keySet = { all: true };
|
|
@@ -558,11 +576,8 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
558
576
|
else {
|
|
559
577
|
transaction.runUpdate(update)
|
|
560
578
|
.then(async () => {
|
|
561
|
-
transaction.commit()
|
|
562
|
-
|
|
563
|
-
resolve();
|
|
564
|
-
})
|
|
565
|
-
.catch(reject);
|
|
579
|
+
await transaction.commit();
|
|
580
|
+
resolve();
|
|
566
581
|
})
|
|
567
582
|
.catch(reject);
|
|
568
583
|
}
|
|
@@ -571,13 +586,81 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
571
586
|
}
|
|
572
587
|
const request = (0, types_1.isPlainObject)(query) ? query : { sql: query };
|
|
573
588
|
request.json = true;
|
|
589
|
+
if (request.params) {
|
|
590
|
+
const types = request.types;
|
|
591
|
+
if ((0, types_1.isPlainObject)(types)) {
|
|
592
|
+
const { Spanner } = require('@google-cloud/spanner');
|
|
593
|
+
for (const attr in types) {
|
|
594
|
+
let value = request.params[attr];
|
|
595
|
+
if (value === undefined) {
|
|
596
|
+
continue;
|
|
597
|
+
}
|
|
598
|
+
const method = types[attr];
|
|
599
|
+
switch (method) {
|
|
600
|
+
case 'date':
|
|
601
|
+
if ((0, types_1.isString)(value)) {
|
|
602
|
+
value = Spanner.date(value);
|
|
603
|
+
}
|
|
604
|
+
else if (Array.isArray(value) && value.length === 3) {
|
|
605
|
+
value = Spanner.date(...value);
|
|
606
|
+
}
|
|
607
|
+
break;
|
|
608
|
+
case 'interval':
|
|
609
|
+
if (Array.isArray(value) && value.length === 3) {
|
|
610
|
+
value = Spanner.interval(value[0], value[1], BigInt(value[2]));
|
|
611
|
+
}
|
|
612
|
+
break;
|
|
613
|
+
case 'float':
|
|
614
|
+
case 'float32':
|
|
615
|
+
case 'int':
|
|
616
|
+
case 'numeric':
|
|
617
|
+
value = Spanner[method](value);
|
|
618
|
+
break;
|
|
619
|
+
case 'protoEnum':
|
|
620
|
+
case 'protoMessage':
|
|
621
|
+
case 'struct':
|
|
622
|
+
if ((0, types_1.isPlainObject)(value)) {
|
|
623
|
+
value = Spanner[method](value);
|
|
624
|
+
}
|
|
625
|
+
break;
|
|
626
|
+
case 'pgJsonb':
|
|
627
|
+
if ((0, types_1.isString)(value) || (0, types_1.isPlainObject)(value)) {
|
|
628
|
+
value = Spanner.pgJsonb(value);
|
|
629
|
+
}
|
|
630
|
+
break;
|
|
631
|
+
case 'pgNumeric':
|
|
632
|
+
if ((0, types_1.isString)(value)) {
|
|
633
|
+
value = Spanner.pgNumeric(value);
|
|
634
|
+
}
|
|
635
|
+
break;
|
|
636
|
+
case 'timestamp':
|
|
637
|
+
value = Spanner.timestamp(value);
|
|
638
|
+
break;
|
|
639
|
+
}
|
|
640
|
+
request.params[attr] = value;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
574
644
|
if (limit > 0) {
|
|
575
645
|
(request.gaxOptions ||= {}).maxResults = limit;
|
|
576
646
|
}
|
|
577
|
-
|
|
647
|
+
if ((flags & 2) === 2) {
|
|
648
|
+
rows = [];
|
|
649
|
+
await new Promise((resolve, reject) => {
|
|
650
|
+
db.runStream(request)
|
|
651
|
+
.on('data', row => {
|
|
652
|
+
rows.push(row);
|
|
653
|
+
})
|
|
654
|
+
.on('end', resolve)
|
|
655
|
+
.on('error', reject);
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
else {
|
|
659
|
+
[rows] = await db.run(request);
|
|
660
|
+
}
|
|
578
661
|
}
|
|
579
662
|
}
|
|
580
|
-
else if (
|
|
663
|
+
else if (isBigtable(item)) {
|
|
581
664
|
if (!name || !table) {
|
|
582
665
|
closeClient();
|
|
583
666
|
throw (0, util_1.formatError)(item, !name ? "Missing database name" : "Missing database table");
|
|
@@ -623,7 +706,7 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
623
706
|
});
|
|
624
707
|
}
|
|
625
708
|
}
|
|
626
|
-
else if (
|
|
709
|
+
else if (isBigQuery(item)) {
|
|
627
710
|
const { params, options = {} } = item;
|
|
628
711
|
if ((0, types_1.isString)(query)) {
|
|
629
712
|
options.query = query;
|
|
@@ -665,14 +748,14 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
665
748
|
[rows] = await instance.query(options);
|
|
666
749
|
}
|
|
667
750
|
}
|
|
668
|
-
else if (
|
|
751
|
+
else if (isDatastore(item)) {
|
|
669
752
|
const { keys, kind, options } = item;
|
|
670
753
|
if (!keys && !kind && !Array.isArray(query)) {
|
|
671
754
|
closeClient();
|
|
672
755
|
throw (0, util_1.formatError)(item, "Missing database query");
|
|
673
756
|
}
|
|
674
757
|
if (useCache) {
|
|
675
|
-
queryString = (keys ? Cloud.asString(keys, true) : (kind ? (name ? '_' + name : '') + '_' + Cloud.asString(kind, true) : '') + '_' + Cloud.asString(query, true)
|
|
758
|
+
queryString = (keys ? Cloud.asString(keys, true) : (kind ? (name ? '_' + name : '') + '_' + Cloud.asString(kind, true) : '') + '_' + Cloud.asString(query, true) + keyLimit(limit)) + (options ? Cloud.asString(options, true) : '');
|
|
676
759
|
if (!update && (rows = this.getCacheResult(service, credential, queryString, cacheValue, ignoreCache))) {
|
|
677
760
|
result[i] = rows;
|
|
678
761
|
continue;
|
|
@@ -742,7 +825,16 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
742
825
|
closeClient();
|
|
743
826
|
throw (0, util_1.formatError)(item, "Missing database table");
|
|
744
827
|
}
|
|
745
|
-
|
|
828
|
+
const db = createClient(item, 3);
|
|
829
|
+
const group = !table.includes('/') && (flags & 1) === 1;
|
|
830
|
+
if (item.aggregateSpec) {
|
|
831
|
+
const col = group ? db.collectionGroup(table) : db.collection(table);
|
|
832
|
+
const data = (await col.aggregate(item.aggregateSpec).get()).data();
|
|
833
|
+
if (data) {
|
|
834
|
+
rows = [data];
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
else if ((0, types_1.isString)(id) || Array.isArray(id)) {
|
|
746
838
|
const options = Array.isArray(id) ? item.options : null;
|
|
747
839
|
if (useCache) {
|
|
748
840
|
queryString = table + '_' + id + (options ? Cloud.asString(options, true) : '');
|
|
@@ -751,7 +843,6 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
751
843
|
continue;
|
|
752
844
|
}
|
|
753
845
|
}
|
|
754
|
-
const db = createClient(item, 3);
|
|
755
846
|
if (Array.isArray(id)) {
|
|
756
847
|
const items = id.map(ref => db.doc(table + '/' + ref));
|
|
757
848
|
if (options) {
|
|
@@ -762,7 +853,7 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
762
853
|
else {
|
|
763
854
|
const doc = db.collection(table).doc(id);
|
|
764
855
|
if ((0, types_1.isPlainObject)(update)) {
|
|
765
|
-
const pattern = /^__(delete|serverTimestamp|increment|vector|
|
|
856
|
+
const pattern = /^__(delete|serverTimestamp|increment|vector|array(?:Union|Remove))(?:<(.+)>)?__$/s;
|
|
766
857
|
for (const attr in update) {
|
|
767
858
|
const match = pattern.exec(attr);
|
|
768
859
|
if (match) {
|
|
@@ -832,81 +923,115 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
832
923
|
}
|
|
833
924
|
}
|
|
834
925
|
}
|
|
835
|
-
else
|
|
836
|
-
const
|
|
837
|
-
if (item.params
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
const orderBy = item.orderBy;
|
|
847
|
-
if (useCache && (rows = this.getCacheResult(service, credential, queryString = table + '_' + Cloud.asString(query, true) + '_' + Cloud.asString(orderBy, true) + (limit > 0 ? '_' + limit : ''), cacheValue, ignoreCache))) {
|
|
848
|
-
result[i] = rows;
|
|
849
|
-
continue;
|
|
926
|
+
else {
|
|
927
|
+
const options = item.options || {};
|
|
928
|
+
if (options.vectorField || item.params || Array.isArray(query)) {
|
|
929
|
+
if (options.vectorField) {
|
|
930
|
+
if (Array.isArray(query)) {
|
|
931
|
+
options.queryVector ||= firestore_1.FieldValue.vector(query);
|
|
932
|
+
}
|
|
933
|
+
if (limit > 0) {
|
|
934
|
+
options.limit = limit;
|
|
935
|
+
}
|
|
936
|
+
rows = (await db.collection(table).findNearest(options).get()).docs.map(doc => doc.data());
|
|
850
937
|
}
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
switch (method) {
|
|
857
|
-
case 'whereAnd':
|
|
858
|
-
case 'whereOr':
|
|
859
|
-
if (!params.every(p => (0, types_1.isArray)(p))) {
|
|
860
|
-
throw (0, types_1.errorMessage)(method, 'Conditionals are not in array format', Cloud.asString(params));
|
|
861
|
-
}
|
|
862
|
-
target = target.where(firestore_1.Filter[method === 'whereAnd' ? 'and' : 'or'](...params.map((p) => firestore_1.Filter.where(p[0], p[1], p[2]))));
|
|
863
|
-
break;
|
|
864
|
-
case 'findNearest':
|
|
865
|
-
params[0] = asFieldPath(params[0]);
|
|
866
|
-
target = target.findNearest.apply(target, params).query;
|
|
867
|
-
break;
|
|
868
|
-
case 'where':
|
|
869
|
-
case 'orderBy':
|
|
870
|
-
params[0] = asFieldPath(params[0]);
|
|
871
|
-
target = target[method].apply(target, params);
|
|
872
|
-
case 'select':
|
|
873
|
-
params.forEach((field, index) => {
|
|
874
|
-
params[index] = asFieldPath(field);
|
|
875
|
-
});
|
|
876
|
-
target = target.select.apply(target, params);
|
|
877
|
-
break;
|
|
878
|
-
case 'endAt':
|
|
879
|
-
case 'endBefore':
|
|
880
|
-
case 'limit':
|
|
881
|
-
case 'limitToLast':
|
|
882
|
-
case 'offset':
|
|
883
|
-
case 'startAfter':
|
|
884
|
-
case 'startAt':
|
|
885
|
-
case 'withConverter':
|
|
886
|
-
target = target[method].apply(target, params);
|
|
887
|
-
break;
|
|
938
|
+
else if (item.params && (options.queryVector || Array.isArray(query) && query.every(value => typeof value === 'number'))) {
|
|
939
|
+
if (!options.queryVector) {
|
|
940
|
+
if (useCache && (rows = this.getCacheResult(service, credential, queryString = table + '_' + Cloud.asString(item.params, true) + '_' + Cloud.asString(query, true) + (options ? Cloud.asString(options, true) : '') + keyLimit(limit), cacheValue, ignoreCache))) {
|
|
941
|
+
result[i] = rows;
|
|
942
|
+
continue;
|
|
888
943
|
}
|
|
944
|
+
options.queryVector = firestore_1.FieldValue.vector(query);
|
|
945
|
+
}
|
|
946
|
+
options.vectorField = asFieldPath(item.params);
|
|
947
|
+
if (limit > 0) {
|
|
948
|
+
options.limit = limit;
|
|
889
949
|
}
|
|
950
|
+
rows = (await db.collection(table).findNearest(options).get()).docs.map(doc => doc.data());
|
|
890
951
|
}
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
952
|
+
else {
|
|
953
|
+
const orderBy = item.orderBy;
|
|
954
|
+
if (useCache && (rows = this.getCacheResult(service, credential, queryString = table + '_' + Cloud.asString(query, true) + '_' + Cloud.asString(orderBy, true) + `_${group ? '1' : '0'}_${typeof id === 'number' ? '1' : '0'}` + keyLimit(limit), cacheValue, ignoreCache))) {
|
|
955
|
+
result[i] = rows;
|
|
956
|
+
continue;
|
|
957
|
+
}
|
|
958
|
+
const targets = [];
|
|
959
|
+
if (group) {
|
|
960
|
+
const col = db.collectionGroup(table);
|
|
961
|
+
if (typeof id === 'number') {
|
|
962
|
+
for await (const partition of col.getPartitions(id)) {
|
|
963
|
+
targets.push(partition.toQuery());
|
|
964
|
+
}
|
|
895
965
|
}
|
|
896
|
-
else
|
|
897
|
-
|
|
966
|
+
else {
|
|
967
|
+
targets.push(col);
|
|
898
968
|
}
|
|
899
969
|
}
|
|
970
|
+
else {
|
|
971
|
+
targets.push(db.collection(table));
|
|
972
|
+
}
|
|
973
|
+
rows = [];
|
|
974
|
+
for (let target of targets) {
|
|
975
|
+
for (const args of query) {
|
|
976
|
+
if ((0, types_1.isArray)(args)) {
|
|
977
|
+
const method = args[0];
|
|
978
|
+
const params = args.slice(1);
|
|
979
|
+
switch (method) {
|
|
980
|
+
case 'whereAnd':
|
|
981
|
+
case 'whereOr':
|
|
982
|
+
if (!params.every(p => (0, types_1.isArray)(p))) {
|
|
983
|
+
throw (0, types_1.errorMessage)(method, 'Conditionals are not in array format', Cloud.asString(params));
|
|
984
|
+
}
|
|
985
|
+
target = target.where(firestore_1.Filter[method === 'whereAnd' ? 'and' : 'or'](...params.map((p) => firestore_1.Filter.where(p[0], p[1], p[2]))));
|
|
986
|
+
break;
|
|
987
|
+
case 'findNearest':
|
|
988
|
+
params[0] = asFieldPath(params[0]);
|
|
989
|
+
target = target.findNearest.apply(target, params).query;
|
|
990
|
+
break;
|
|
991
|
+
case 'where':
|
|
992
|
+
case 'orderBy':
|
|
993
|
+
params[0] = asFieldPath(params[0]);
|
|
994
|
+
target = target[method].apply(target, params);
|
|
995
|
+
case 'select':
|
|
996
|
+
params.forEach((field, index) => {
|
|
997
|
+
params[index] = asFieldPath(field);
|
|
998
|
+
});
|
|
999
|
+
target = target.select.apply(target, params);
|
|
1000
|
+
break;
|
|
1001
|
+
case 'endAt':
|
|
1002
|
+
case 'endBefore':
|
|
1003
|
+
case 'limit':
|
|
1004
|
+
case 'limitToLast':
|
|
1005
|
+
case 'offset':
|
|
1006
|
+
case 'startAfter':
|
|
1007
|
+
case 'startAt':
|
|
1008
|
+
case 'withConverter':
|
|
1009
|
+
target = target[method].apply(target, params);
|
|
1010
|
+
break;
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
if (Array.isArray(orderBy)) {
|
|
1015
|
+
for (const order of orderBy) {
|
|
1016
|
+
if ((0, types_1.isArray)(order)) {
|
|
1017
|
+
target = target.orderBy(asFieldPath(order[0]), order[1]);
|
|
1018
|
+
}
|
|
1019
|
+
else if ((0, types_1.isString)(order)) {
|
|
1020
|
+
target = target.orderBy(order);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
if (limit > 0) {
|
|
1025
|
+
target = target.limit(limit);
|
|
1026
|
+
}
|
|
1027
|
+
rows = rows.concat((await target.get()).docs.map(doc => doc.data()));
|
|
1028
|
+
}
|
|
900
1029
|
}
|
|
901
|
-
if (limit > 0) {
|
|
902
|
-
target = target.limit(limit);
|
|
903
|
-
}
|
|
904
|
-
rows = (await target.get()).docs.map(doc => doc.data());
|
|
905
1030
|
}
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
1031
|
+
else {
|
|
1032
|
+
closeClient();
|
|
1033
|
+
throw (0, util_1.formatError)(item, "Missing database query");
|
|
1034
|
+
}
|
|
910
1035
|
}
|
|
911
1036
|
}
|
|
912
1037
|
else {
|
|
@@ -1041,6 +1166,7 @@ function createBucketRequest(credential) {
|
|
|
1041
1166
|
case 'location':
|
|
1042
1167
|
case 'locationType':
|
|
1043
1168
|
case 'logging':
|
|
1169
|
+
case 'generation':
|
|
1044
1170
|
case 'metageneration':
|
|
1045
1171
|
case 'name':
|
|
1046
1172
|
case 'objectRetention':
|
|
@@ -1048,6 +1174,8 @@ function createBucketRequest(credential) {
|
|
|
1048
1174
|
case 'projectNumber':
|
|
1049
1175
|
case 'retentionPolicy':
|
|
1050
1176
|
case 'rpo':
|
|
1177
|
+
case 'softDeleteTime':
|
|
1178
|
+
case 'hardDeleteTime':
|
|
1051
1179
|
case 'softDeletePolicy':
|
|
1052
1180
|
case 'storageClass':
|
|
1053
1181
|
case 'timeCreated':
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-r/gcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "Google (GCP) cloud functions for E-mc.",
|
|
5
5
|
"main": "client/index.js",
|
|
6
6
|
"publishConfig": {
|
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
"license": "MIT",
|
|
20
20
|
"homepage": "https://github.com/anpham6/pi-r#readme",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@e-mc/cloud": "^0.
|
|
23
|
-
"@e-mc/module": "^0.
|
|
24
|
-
"@e-mc/types": "^0.
|
|
22
|
+
"@e-mc/cloud": "^0.12.3",
|
|
23
|
+
"@e-mc/module": "^0.12.3",
|
|
24
|
+
"@e-mc/types": "^0.12.3",
|
|
25
25
|
"@google-cloud/firestore": "^7.11.0",
|
|
26
|
-
"@google-cloud/storage": "^7.
|
|
26
|
+
"@google-cloud/storage": "^7.16.0"
|
|
27
27
|
}
|
|
28
28
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -2,8 +2,10 @@ import type { CloudDatabase, CloudStorage } from '@e-mc/types/lib/cloud';
|
|
|
2
2
|
|
|
3
3
|
import type { StorageOptions } from '@google-cloud/storage';
|
|
4
4
|
import type { PathType } from '@google-cloud/datastore';
|
|
5
|
+
import type { AggregateSpec } from '@google-cloud/firestore';
|
|
5
6
|
import type { entity } from '@google-cloud/datastore/build/src/entity';
|
|
6
7
|
import type { FirebaseOptions as IFirebaseOptions } from '@firebase/app';
|
|
8
|
+
import type { ServiceAccount } from 'firebase-admin/app';
|
|
7
9
|
|
|
8
10
|
// @ts-ignore
|
|
9
11
|
import type { GoogleAuthOptions } from 'google-auth-library';
|
|
@@ -17,19 +19,21 @@ export interface GCPDatabaseQuery<T = PlainObject> extends Omit<CloudDatabase<un
|
|
|
17
19
|
service: "gcp" | "gcloud";
|
|
18
20
|
product?: "firestore" | "firebase" | "bigquery" | "bigtable" | "datastore" | "spanner";
|
|
19
21
|
database?: string;
|
|
20
|
-
id?: string | string[];
|
|
22
|
+
id?: string | string[] | number;
|
|
21
23
|
updateType?: 0 | 1 | 2 | 3;
|
|
22
24
|
columns?: string[];
|
|
23
25
|
keys?: DatastoreKey | DatastoreKey[];
|
|
24
26
|
kind?: string | string[];
|
|
25
27
|
orderBy?: unknown[][];
|
|
28
|
+
aggregateSpec?: AggregateSpec;
|
|
29
|
+
flags?: number;
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
export type GCPDatabaseCredential = GoogleAuthOptions;
|
|
29
33
|
|
|
30
34
|
export interface FirebaseOptions extends IFirebaseOptions {
|
|
31
35
|
product?: "firebase";
|
|
32
|
-
admin?: boolean;
|
|
36
|
+
admin?: boolean | string | ServiceAccount;
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
export type DatastoreKey = string | PathType[] | entity.KeyOptions;
|
package/upload/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
const path = require("node:path");
|
|
3
3
|
const fs = require("node:fs");
|
|
4
4
|
const stream = require("node:stream");
|
|
5
|
+
const storage_1 = require("@google-cloud/storage");
|
|
5
6
|
const Cloud = require("@e-mc/cloud");
|
|
6
7
|
const types_1 = require("@e-mc/types");
|
|
7
8
|
const util_1 = require("@e-mc/cloud/util");
|
|
@@ -61,9 +62,9 @@ function upload(credential, service = 'gcp') {
|
|
|
61
62
|
this.formatMessage(64, service, ["Bucket configured" + ` (${feature})`, bucket], message, { ...Cloud.LOG_CLOUD_COMMAND });
|
|
62
63
|
};
|
|
63
64
|
if (typeof retentionPolicy === 'number') {
|
|
64
|
-
bucketClient.setRetentionPeriod(retentionPolicy)
|
|
65
|
+
(retentionPolicy === 0 ? bucketClient.removeRetentionPeriod() : bucketClient.setRetentionPeriod(retentionPolicy))
|
|
65
66
|
.then(([response]) => {
|
|
66
|
-
commandMessage('Retention Policy', response.retentionPolicy?.effectiveTime);
|
|
67
|
+
commandMessage('Retention Policy', response.retentionPolicy?.[retentionPolicy === 0 ? 'retentionPeriod' : 'effectiveTime']);
|
|
67
68
|
})
|
|
68
69
|
.catch(addLog);
|
|
69
70
|
}
|
|
@@ -298,11 +299,10 @@ function upload(credential, service = 'gcp') {
|
|
|
298
299
|
params.predefinedAcl = acl;
|
|
299
300
|
}
|
|
300
301
|
}
|
|
301
|
-
const file = bucketClient.file(destination);
|
|
302
|
+
const file = bucketClient.file(destination, params);
|
|
302
303
|
let uploadClient;
|
|
303
304
|
if (Path[i]) {
|
|
304
|
-
|
|
305
|
-
uploadClient = new TransferManager(bucketClient).uploadFileInChunks(Path[i], { uploadName: destination, chunkSizeBytes, headers, concurrencyLimit: data.upload.chunkLimit || concurrencyLimit, maxQueueSize });
|
|
305
|
+
uploadClient = new storage_1.TransferManager(bucketClient).uploadFileInChunks(Path[i], { uploadName: destination, chunkSizeBytes, headers, concurrencyLimit: data.upload.chunkLimit || concurrencyLimit, maxQueueSize });
|
|
306
306
|
}
|
|
307
307
|
else {
|
|
308
308
|
params.resumable ??= false;
|
|
@@ -316,8 +316,11 @@ function upload(credential, service = 'gcp') {
|
|
|
316
316
|
.on('error', reject);
|
|
317
317
|
});
|
|
318
318
|
}
|
|
319
|
+
else {
|
|
320
|
+
uploadClient = file.save(Body[i], params);
|
|
321
|
+
}
|
|
319
322
|
}
|
|
320
|
-
|
|
323
|
+
uploadClient
|
|
321
324
|
.then(async () => {
|
|
322
325
|
const url = getURL(file.name);
|
|
323
326
|
this.formatMessage(64, service, "Upload success", url, { ...Cloud.LOG_CLOUD_UPLOAD });
|