@shushed/helpers 0.0.27 → 0.0.28

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/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ import { PubSub, Topic, Subscription } from '@google-cloud/pubsub';
5
5
  import * as _google_cloud_scheduler_build_protos_protos from '@google-cloud/scheduler/build/protos/protos';
6
6
  import { CloudSchedulerClient } from '@google-cloud/scheduler';
7
7
  import { SecretManagerServiceClient } from '@google-cloud/secret-manager';
8
+ import { BigQuery } from '@google-cloud/bigquery';
8
9
 
9
10
  declare const schema$l: {
10
11
  readonly $schema: "http://json-schema.org/draft-07/schema#";
@@ -28743,12 +28744,14 @@ declare class PubSubHelper extends Runtime {
28743
28744
  createOrUpdate(opts: {
28744
28745
  topicName: string;
28745
28746
  dlq: boolean;
28747
+ bigQueryTableId?: string | null;
28746
28748
  retryLimit: number;
28747
28749
  retryDelay: number;
28748
28750
  ackDeadline: number;
28749
28751
  }): Promise<{
28750
28752
  topic: Topic;
28751
28753
  dlqTopic: Topic | null;
28754
+ bqSubscription: Subscription | null;
28752
28755
  dlqSubscription: Subscription | null;
28753
28756
  subscription: Subscription;
28754
28757
  }>;
@@ -28799,7 +28802,7 @@ declare class SchedulerHelper extends Runtime {
28799
28802
  timezone: string;
28800
28803
  }): Promise<{
28801
28804
  status: _google_cloud_scheduler_build_protos_protos.google.rpc.IStatus | null | undefined;
28802
- state: _google_cloud_scheduler_build_protos_protos.google.cloud.scheduler.v1.Job.State | "STATE_UNSPECIFIED" | "ENABLED" | "PAUSED" | "DISABLED" | "UPDATE_FAILED" | null | undefined;
28805
+ state: "STATE_UNSPECIFIED" | _google_cloud_scheduler_build_protos_protos.google.cloud.scheduler.v1.Job.State | "ENABLED" | "PAUSED" | "DISABLED" | "UPDATE_FAILED" | null | undefined;
28803
28806
  name: string | null | undefined;
28804
28807
  httpTarget: _google_cloud_scheduler_build_protos_protos.google.cloud.scheduler.v1.IHttpTarget | null | undefined;
28805
28808
  pubsubTarget: _google_cloud_scheduler_build_protos_protos.google.cloud.scheduler.v1.IPubsubTarget | null | undefined;
@@ -28809,7 +28812,7 @@ declare class SchedulerHelper extends Runtime {
28809
28812
  timezone: string;
28810
28813
  }): Promise<{
28811
28814
  status: _google_cloud_scheduler_build_protos_protos.google.rpc.IStatus | null | undefined;
28812
- state: _google_cloud_scheduler_build_protos_protos.google.cloud.scheduler.v1.Job.State | "STATE_UNSPECIFIED" | "ENABLED" | "PAUSED" | "DISABLED" | "UPDATE_FAILED" | null | undefined;
28815
+ state: "STATE_UNSPECIFIED" | _google_cloud_scheduler_build_protos_protos.google.cloud.scheduler.v1.Job.State | "ENABLED" | "PAUSED" | "DISABLED" | "UPDATE_FAILED" | null | undefined;
28813
28816
  name: string | null | undefined;
28814
28817
  httpTarget: _google_cloud_scheduler_build_protos_protos.google.cloud.scheduler.v1.IHttpTarget | null | undefined;
28815
28818
  pubsubTarget: _google_cloud_scheduler_build_protos_protos.google.cloud.scheduler.v1.IPubsubTarget | null | undefined;
@@ -28833,6 +28836,21 @@ declare class JWKSHelper extends Runtime {
28833
28836
  private fetchJWKS;
28834
28837
  }
28835
28838
 
28839
+ interface ColumnSchema {
28840
+ name: string;
28841
+ type: string;
28842
+ mode?: string;
28843
+ }
28844
+ declare class BigQueryHelper extends Runtime {
28845
+ private bigQuery;
28846
+ constructor(opts: Opts, bigQuery: BigQuery);
28847
+ createOrUpdate(opts: {
28848
+ datasetId: string;
28849
+ tableName: string;
28850
+ incomingSchema: ColumnSchema[];
28851
+ }): Promise<string>;
28852
+ }
28853
+
28836
28854
  type TriggerOnExecuteOptions = {
28837
28855
  req: {
28838
28856
  status?: number;
@@ -28979,6 +28997,8 @@ type TriggerOnCreateOptions = {
28979
28997
  };
28980
28998
  };
28981
28999
 
29000
+ type index_BigQueryHelper = BigQueryHelper;
29001
+ declare const index_BigQueryHelper: typeof BigQueryHelper;
28982
29002
  type index_EnvEngine = EnvEngine;
28983
29003
  declare const index_EnvEngine: typeof EnvEngine;
28984
29004
  type index_JWKSHelper = JWKSHelper;
@@ -29000,7 +29020,7 @@ declare const index_sanitizeToString: typeof sanitizeToString;
29000
29020
  declare const index_validate: typeof validate;
29001
29021
  declare const index_validateGoogleAuth: typeof validateGoogleAuth;
29002
29022
  declare namespace index {
29003
- export { index_EnvEngine as EnvEngine, index_JWKSHelper as JWKSHelper, index_PubSubHelper as PubSubHelper, index_Runtime as Runtime, index_SchedulerHelper as SchedulerHelper, index_Secrets as Secrets, type index_TriggerOnCreateOptions as TriggerOnCreateOptions, type index_TriggerOnExecuteOptions as TriggerOnExecuteOptions, index_isCronMessage as isCronMessage, index_isPubSubRequest as isPubSubRequest, index_sanitize as sanitize, index_sanitizeToString as sanitizeToString, index_validate as validate, index_validateGoogleAuth as validateGoogleAuth };
29023
+ export { index_BigQueryHelper as BigQueryHelper, index_EnvEngine as EnvEngine, index_JWKSHelper as JWKSHelper, index_PubSubHelper as PubSubHelper, index_Runtime as Runtime, index_SchedulerHelper as SchedulerHelper, index_Secrets as Secrets, type index_TriggerOnCreateOptions as TriggerOnCreateOptions, type index_TriggerOnExecuteOptions as TriggerOnExecuteOptions, index_isCronMessage as isCronMessage, index_isPubSubRequest as isPubSubRequest, index_sanitize as sanitize, index_sanitizeToString as sanitizeToString, index_validate as validate, index_validateGoogleAuth as validateGoogleAuth };
29004
29024
  }
29005
29025
 
29006
29026
  export { index as lib, index$9 as schema, index$1 as types };
package/dist/index.js CHANGED
@@ -280,6 +280,7 @@ var shipped_exports2 = {};
280
280
  // src-public/index.ts
281
281
  var src_public_exports = {};
282
282
  __export(src_public_exports, {
283
+ BigQueryHelper: () => bigquery_default,
283
284
  EnvEngine: () => env_default,
284
285
  JWKSHelper: () => jwks_default,
285
286
  PubSubHelper: () => pubsub_default,
@@ -631,6 +632,9 @@ var AES256GCM = class {
631
632
  var env_default = EnvEngine;
632
633
 
633
634
  // src-public/pubsub.ts
635
+ function isSubscriptionOptionsPush(opts) {
636
+ return "endpointUrl" in opts;
637
+ }
634
638
  var PubSubHelper = class extends Runtime {
635
639
  constructor(opts, pubSub) {
636
640
  super(opts);
@@ -648,6 +652,18 @@ var PubSubHelper = class extends Runtime {
648
652
  dlqSubscription = await this.ensureDLQSubscriptionExists(dlqSubscriptionName, {
649
653
  topic: dlqTopic
650
654
  });
655
+ } else {
656
+ await this.deleteSubscription(`${subscriptionName}-dlq`);
657
+ }
658
+ let bqSubscription = null;
659
+ if (opts.bigQueryTableId) {
660
+ const bigQuerySubscriptionName = `${subscriptionName}-bq`;
661
+ bqSubscription = await this.ensureSubscribtionExists(bigQuerySubscriptionName, {
662
+ topic,
663
+ tableId: opts.bigQueryTableId
664
+ });
665
+ } else {
666
+ await this.deleteSubscription(`${subscriptionName}-bq`);
651
667
  }
652
668
  const subscription = await this.ensureSubscribtionExists(subscriptionName, {
653
669
  topic,
@@ -661,6 +677,7 @@ var PubSubHelper = class extends Runtime {
661
677
  return {
662
678
  topic,
663
679
  dlqTopic,
680
+ bqSubscription,
664
681
  dlqSubscription,
665
682
  subscription
666
683
  };
@@ -689,40 +706,58 @@ var PubSubHelper = class extends Runtime {
689
706
  let subscription = subscriptions.find((subscription2) => this.getNameFromFullyQualifiedName(subscription2.name) === subscriptionName);
690
707
  let endpointHasChanged = false;
691
708
  let retryLimitHasChanged = false;
709
+ let ackDeadlineHasChanged = false;
692
710
  let retryDelayHasChanged = false;
693
711
  let shouldRecreate = false;
694
712
  let dlqHasChanged = false;
713
+ let tableIdHasChanged = false;
695
714
  if (subscription) {
696
715
  const [subscriptionMetaData] = await subscription.getMetadata();
697
- endpointHasChanged = subscriptionMetaData.pushConfig?.pushEndpoint != opts.endpointUrl;
698
- retryDelayHasChanged = subscriptionMetaData.retryPolicy?.minimumBackoff?.seconds != opts.retryMinDelay;
699
- retryLimitHasChanged = subscriptionMetaData.deadLetterPolicy?.maxDeliveryAttempts != opts.retryLimit;
700
- dlqHasChanged = !subscriptionMetaData.deadLetterPolicy && !!opts.dlqTopic || !!subscriptionMetaData.deadLetterPolicy?.deadLetterTopic && !opts.dlqTopic;
701
- shouldRecreate = endpointHasChanged || retryDelayHasChanged || retryLimitHasChanged || dlqHasChanged;
716
+ if (!isSubscriptionOptionsPush(opts)) {
717
+ tableIdHasChanged = (subscriptionMetaData.bigqueryConfig?.table || null) !== (opts.tableId || null);
718
+ } else {
719
+ endpointHasChanged = subscriptionMetaData.pushConfig?.pushEndpoint != opts.endpointUrl;
720
+ dlqHasChanged = !subscriptionMetaData.deadLetterPolicy && !!opts.dlqTopic || !!subscriptionMetaData.deadLetterPolicy?.deadLetterTopic && !opts.dlqTopic;
721
+ retryDelayHasChanged = subscriptionMetaData.retryPolicy?.minimumBackoff?.seconds != opts.retryMinDelay;
722
+ retryLimitHasChanged = subscriptionMetaData.deadLetterPolicy?.maxDeliveryAttempts != opts.retryLimit;
723
+ ackDeadlineHasChanged = subscriptionMetaData.ackDeadlineSeconds !== (opts.ackDeadline || 90);
724
+ }
725
+ shouldRecreate = endpointHasChanged || retryDelayHasChanged || retryLimitHasChanged || dlqHasChanged || tableIdHasChanged || ackDeadlineHasChanged;
702
726
  }
703
727
  if (subscription && shouldRecreate) {
704
728
  await subscription.delete();
705
729
  }
706
- if (!subscription || shouldRecreate) {
707
- await opts.topic.createSubscription(subscriptionName, Object.assign({
708
- ackDeadlineSeconds: opts.ackDeadline || 90,
709
- pushConfig: {
710
- pushEndpoint: opts.endpointUrl,
711
- oidcToken: {
712
- serviceAccountEmail: `runtime@${process.env.GCLOUD_PROJECT}.iam.gserviceaccount.com`,
713
- audience: process.env.GCLOUD_PROJECT + "/" + this.triggerId
714
- }
715
- },
716
- retryPolicy: {
717
- minimumBackoff: { seconds: opts.retryMinDelay },
718
- maximumBackoff: { seconds: opts.retryMaxDelay }
730
+ const payload = {};
731
+ if (!isSubscriptionOptionsPush(opts)) {
732
+ payload.ackDeadlineSeconds = 60;
733
+ payload.bigqueryConfig = {
734
+ table: opts.tableId,
735
+ writeMetadata: true,
736
+ dropUnknownFields: true,
737
+ useTableSchema: true
738
+ };
739
+ } else {
740
+ payload.ackDeadlineSeconds = opts.ackDeadline || 90;
741
+ payload.pushConfig = {
742
+ pushEndpoint: opts.endpointUrl,
743
+ oidcToken: {
744
+ serviceAccountEmail: `runtime@${process.env.GCLOUD_PROJECT}.iam.gserviceaccount.com`,
745
+ audience: process.env.GCLOUD_PROJECT + "/" + this.triggerId
719
746
  }
720
- }, opts.dlqTopic ? {
721
- deadLetterPolicy: {
747
+ };
748
+ payload.retryPolicy = {
749
+ minimumBackoff: { seconds: opts.retryMinDelay },
750
+ maximumBackoff: { seconds: opts.retryMaxDelay }
751
+ };
752
+ if (opts.dlqTopic) {
753
+ payload.deadLetterPolicy = {
722
754
  deadLetterTopic: opts.dlqTopic.name,
723
755
  maxDeliveryAttempts: opts.retryLimit
724
- }
725
- } : {}));
756
+ };
757
+ }
758
+ }
759
+ if (!subscription || shouldRecreate) {
760
+ await opts.topic.createSubscription(subscriptionName, payload);
726
761
  [subscriptions] = await opts.topic.getSubscriptions();
727
762
  subscription = subscriptions.find((subscription2) => this.getNameFromFullyQualifiedName(subscription2.name) === subscriptionName);
728
763
  }
@@ -942,6 +977,64 @@ var Secrets = class extends Runtime {
942
977
  }
943
978
  };
944
979
  var secret_default = Secrets;
980
+
981
+ // src-public/bigquery.ts
982
+ var BigQueryHelper = class extends Runtime {
983
+ constructor(opts, bigQuery) {
984
+ super(opts);
985
+ this.bigQuery = bigQuery;
986
+ }
987
+ async createOrUpdate(opts) {
988
+ const { datasetId, tableName, incomingSchema } = opts;
989
+ const dataset = this.bigQuery.dataset(datasetId);
990
+ const table = dataset.table(tableName);
991
+ const fullTableId = `${this.bigQuery.projectId}.${datasetId}.${tableName}`;
992
+ const [tableExists] = await table.exists();
993
+ if (!tableExists) {
994
+ throw new Error(`Table ${fullTableId} does not exist.`);
995
+ }
996
+ const [metadata] = await table.getMetadata();
997
+ const existingSchema = metadata.schema.fields;
998
+ const alterStatements = [];
999
+ const existingColumnsMap = new Map(
1000
+ existingSchema.map((col) => [col.name.toLowerCase(), col])
1001
+ );
1002
+ const incomingColumnsMap = new Map(
1003
+ incomingSchema.map((col) => [col.name.toLowerCase(), col])
1004
+ );
1005
+ const currentDate = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10).replace(/-/g, "");
1006
+ for (const incomingCol of incomingSchema) {
1007
+ const existingCol = existingColumnsMap.get(incomingCol.name.toLowerCase());
1008
+ if (!existingCol) {
1009
+ alterStatements.push(
1010
+ `ALTER TABLE \`${fullTableId}\` ADD COLUMN \`${incomingCol.name}\` ${incomingCol.type}${incomingCol.mode === "REPEATED" ? " REPEATED" : ""};`
1011
+ );
1012
+ } else if (existingCol.type !== incomingCol.type || incomingCol.mode && existingCol.mode !== incomingCol.mode) {
1013
+ const renamed = `${incomingCol.name}${currentDate}`;
1014
+ alterStatements.push(
1015
+ `ALTER TABLE \`${fullTableId}\` RENAME COLUMN \`${incomingCol.name}\` TO \`${renamed}\`;`
1016
+ );
1017
+ alterStatements.push(
1018
+ `ALTER TABLE \`${fullTableId}\` ADD COLUMN \`${incomingCol.name}\` ${incomingCol.type}${incomingCol.mode === "REPEATED" ? " REPEATED" : ""};`
1019
+ );
1020
+ }
1021
+ }
1022
+ for (const existingCol of existingSchema) {
1023
+ if (!incomingColumnsMap.has(existingCol.name.toLowerCase())) {
1024
+ const renamed = `${existingCol.name}${currentDate}`;
1025
+ alterStatements.push(
1026
+ `ALTER TABLE \`${fullTableId}\` RENAME COLUMN \`${existingCol.name}\` TO \`${renamed}\`;`
1027
+ );
1028
+ }
1029
+ }
1030
+ for (const sql of alterStatements) {
1031
+ console.log(`Executing SQL: ${sql}`);
1032
+ await this.bigQuery.query({ query: sql });
1033
+ }
1034
+ return fullTableId;
1035
+ }
1036
+ };
1037
+ var bigquery_default = BigQueryHelper;
945
1038
  // Annotate the CommonJS export names for ESM import in node:
946
1039
  0 && (module.exports = {
947
1040
  lib,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shushed/helpers",
3
- "version": "0.0.27",
3
+ "version": "0.0.28",
4
4
  "author": "",
5
5
  "license": "UNLICENSED",
6
6
  "description": "",