@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 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
- const { getApps, initializeApp, applicationDefault } = require('firebase-admin/app');
59
- let app;
60
- for (const item of getApps()) {
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
- if (isDB) {
71
- const { getDatabase } = require('firebase-admin/database');
72
- return getDatabase(app);
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) => (err instanceof Error) && err.code === 409;
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
- let packageName = '';
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
- const { product, name, table, query, database } = data;
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 (product === "bigquery" || !product && (!name && table && database || (0, types_1.isString)(query))) {
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 (product === "datastore" || !product && (data.keys || data.kind || query && !table && !data.id)) {
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 (product === "spanner" || !product && name && database && (query || table)) {
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 > 0 ? '_' + 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 ((0, types_1.isObject)(columns)) {
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
- .then(() => {
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
- [rows] = await db.run(request);
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 (product === "bigtable" || !product && name && table && !database) {
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 (product === "bigquery" || !product && (!name && database && table || (0, types_1.isString)(query) || (0, types_1.isString)(item.options?.query))) {
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 (product === "datastore" || !product && (item.keys || item.kind || query && !table && !id)) {
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)) + (limit > 0 ? '_' + limit : 0) + (options ? Cloud.asString(options, 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
- if (id) {
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|(?:array)(?:Union|Remove))(?:<(.+)>)?__$/s;
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 if (Array.isArray(query)) {
836
- const db = createClient(item, 3).collection(table);
837
- if (item.params && query.every(value => typeof value === 'number')) {
838
- const options = item.options;
839
- if (useCache && (rows = this.getCacheResult(service, credential, queryString = table + '_' + Cloud.asString(item.params, true) + '_' + Cloud.asString(query, true) + (options ? Cloud.asString(options, true) : ''), cacheValue, ignoreCache))) {
840
- result[i] = rows;
841
- continue;
842
- }
843
- rows = (await db.findNearest(asFieldPath(item.params), firestore_1.FieldValue.vector(query), options).get()).docs.map(doc => doc.data());
844
- }
845
- else {
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
- let target = db;
852
- for (const args of query) {
853
- if ((0, types_1.isArray)(args)) {
854
- const method = args[0];
855
- const params = args.slice(1);
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
- if (Array.isArray(orderBy)) {
892
- for (const order of orderBy) {
893
- if ((0, types_1.isArray)(order)) {
894
- target = target.orderBy(asFieldPath(order[0]), order[1]);
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 if ((0, types_1.isString)(order)) {
897
- target = target.orderBy(order);
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
- else {
908
- closeClient();
909
- throw (0, util_1.formatError)(item, "Missing database query");
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.9.4",
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.11.5",
23
- "@e-mc/module": "^0.11.5",
24
- "@e-mc/types": "^0.11.5",
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.15.2"
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
- const { TransferManager } = require('@google-cloud/storage');
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
- (uploadClient || file.save(Body[i], params))
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 });