@shushed/helpers 0.0.28 → 0.0.30

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
@@ -2,6 +2,7 @@ import { JSONSchemaType } from 'ajv';
2
2
  import { DeepRedact } from '@hackylabs/deep-redact';
3
3
  import { Firestore, DocumentReference } from '@google-cloud/firestore';
4
4
  import { PubSub, Topic, Subscription } from '@google-cloud/pubsub';
5
+ import { Context } from 'co-body';
5
6
  import * as _google_cloud_scheduler_build_protos_protos from '@google-cloud/scheduler/build/protos/protos';
6
7
  import { CloudSchedulerClient } from '@google-cloud/scheduler';
7
8
  import { SecretManagerServiceClient } from '@google-cloud/secret-manager';
@@ -28721,6 +28722,8 @@ declare const isCronMessage: (headers: Record<string, string>) => boolean;
28721
28722
  declare const validateGoogleAuth: (opts: Opts & {
28722
28723
  serviceAccount?: string | null;
28723
28724
  }, headers: Record<string, string>, firestore: Firestore) => Promise<void>;
28725
+ declare const parseDateOrDefault: (date: string | null | Date, defaultValue?: Date | null) => Date | null;
28726
+ declare function getEventTime(x: any, defaultValue: Date | null): Date | null;
28724
28727
 
28725
28728
  type Level = 'env' | 'workflow' | 'trigger';
28726
28729
  declare class EnvEngine extends Runtime {
@@ -28738,9 +28741,37 @@ declare class EnvEngine extends Runtime {
28738
28741
  get(key: string, level?: Level, decryptWithValue?: string): Promise<string>;
28739
28742
  }
28740
28743
 
28744
+ type Message = {
28745
+ buildshipId: string;
28746
+ body: string;
28747
+ sourceSystem: string;
28748
+ targetSystem: string;
28749
+ processStartedAt: Date | null;
28750
+ recordModifiedAt: Date | null;
28751
+ originalPublishTime: Date | null;
28752
+ publishTime: Date | null;
28753
+ };
28754
+ type LastModifiedKeys = 'last_modified_date_time' | 'last_modified_date' | 'last_modified_datetime' | 'record_modified_at' | 'lastModifiedDateTime' | 'lastModifiedAt' | 'last_modified_at' | 'SystemModifiedAt' | 'system_modified_at' | 'lastUpdatedAt' | 'modified_at' | 'last_updated_at' | 'modifiedAt';
28755
+ type AtLeastOne<T, Keys extends keyof T = keyof T> = Partial<T> & {
28756
+ [K in Keys]-?: Required<Pick<T, K>> & Partial<Record<Exclude<Keys, K>, never>>;
28757
+ }[Keys];
28758
+ type MessageBody = {
28759
+ [K in LastModifiedKeys]?: Date | string;
28760
+ } & {
28761
+ [key: string]: any;
28762
+ };
28741
28763
  declare class PubSubHelper extends Runtime {
28742
28764
  private pubSub;
28743
28765
  constructor(opts: Opts, pubSub: PubSub);
28766
+ static decodeMessageFromRequest(req: Context): Promise<Message>;
28767
+ publish(options: Partial<Message> & {
28768
+ topicName: string;
28769
+ sourceSystem: string;
28770
+ }, payload: AtLeastOne<MessageBody, LastModifiedKeys>[], orgMessage?: Message): Promise<string[]>;
28771
+ publish(options: Partial<Message> & {
28772
+ topicName: string;
28773
+ sourceSystem: string;
28774
+ }, payload: AtLeastOne<MessageBody, LastModifiedKeys>, orgMessage?: Message): Promise<string[]>;
28744
28775
  createOrUpdate(opts: {
28745
28776
  topicName: string;
28746
28777
  dlq: boolean;
@@ -29003,6 +29034,7 @@ type index_EnvEngine = EnvEngine;
29003
29034
  declare const index_EnvEngine: typeof EnvEngine;
29004
29035
  type index_JWKSHelper = JWKSHelper;
29005
29036
  declare const index_JWKSHelper: typeof JWKSHelper;
29037
+ type index_Message = Message;
29006
29038
  type index_PubSubHelper = PubSubHelper;
29007
29039
  declare const index_PubSubHelper: typeof PubSubHelper;
29008
29040
  type index_Runtime = Runtime;
@@ -29013,14 +29045,16 @@ type index_Secrets = Secrets;
29013
29045
  declare const index_Secrets: typeof Secrets;
29014
29046
  type index_TriggerOnCreateOptions = TriggerOnCreateOptions;
29015
29047
  type index_TriggerOnExecuteOptions = TriggerOnExecuteOptions;
29048
+ declare const index_getEventTime: typeof getEventTime;
29016
29049
  declare const index_isCronMessage: typeof isCronMessage;
29017
29050
  declare const index_isPubSubRequest: typeof isPubSubRequest;
29051
+ declare const index_parseDateOrDefault: typeof parseDateOrDefault;
29018
29052
  declare const index_sanitize: typeof sanitize;
29019
29053
  declare const index_sanitizeToString: typeof sanitizeToString;
29020
29054
  declare const index_validate: typeof validate;
29021
29055
  declare const index_validateGoogleAuth: typeof validateGoogleAuth;
29022
29056
  declare namespace index {
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 };
29057
+ export { index_BigQueryHelper as BigQueryHelper, index_EnvEngine as EnvEngine, index_JWKSHelper as JWKSHelper, type index_Message as Message, 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_getEventTime as getEventTime, index_isCronMessage as isCronMessage, index_isPubSubRequest as isPubSubRequest, index_parseDateOrDefault as parseDateOrDefault, index_sanitize as sanitize, index_sanitizeToString as sanitizeToString, index_validate as validate, index_validateGoogleAuth as validateGoogleAuth };
29024
29058
  }
29025
29059
 
29026
29060
  export { index as lib, index$9 as schema, index$1 as types };
package/dist/index.js CHANGED
@@ -287,8 +287,10 @@ __export(src_public_exports, {
287
287
  Runtime: () => Runtime,
288
288
  SchedulerHelper: () => scheduler_default,
289
289
  Secrets: () => secret_default,
290
+ getEventTime: () => getEventTime,
290
291
  isCronMessage: () => isCronMessage,
291
292
  isPubSubRequest: () => isPubSubRequest,
293
+ parseDateOrDefault: () => parseDateOrDefault,
292
294
  sanitize: () => sanitize,
293
295
  sanitizeToString: () => sanitizeToString,
294
296
  validate: () => validate,
@@ -486,6 +488,49 @@ var validateGoogleAuth = async (opts, headers, firestore) => {
486
488
  throw new Error("Invalid authorization header " + err.message);
487
489
  }
488
490
  };
491
+ var parseDateOrDefault = (date, defaultValue = null) => {
492
+ if (!date) {
493
+ return defaultValue;
494
+ }
495
+ if (date instanceof Date) {
496
+ if (isNaN(date.getTime())) {
497
+ return defaultValue;
498
+ }
499
+ return date;
500
+ }
501
+ const dateObj = new Date(date);
502
+ if (isNaN(dateObj.getTime())) {
503
+ return defaultValue;
504
+ }
505
+ return dateObj;
506
+ };
507
+ function getEventTime(x, defaultValue) {
508
+ const possibleKeys = [
509
+ "last_modified_date_time",
510
+ "record_modified_at",
511
+ "last_modified_date",
512
+ "last_modified_datetime",
513
+ "last_modified_date_time",
514
+ "lastModifiedDateTime",
515
+ "lastModifiedAt",
516
+ "last_modified_at",
517
+ "SystemModifiedAt",
518
+ "system_modified_at",
519
+ "lastUpdatedAt",
520
+ "modified_at",
521
+ "last_updated_at",
522
+ "modifiedAt"
523
+ ];
524
+ for (let i = 0; i < possibleKeys.length; i++) {
525
+ if (x[possibleKeys[i]]) {
526
+ const possibleDateTime = new Date(x[possibleKeys[i]]);
527
+ if (!isNaN(possibleDateTime.getTime())) {
528
+ return possibleDateTime;
529
+ }
530
+ }
531
+ }
532
+ return defaultValue;
533
+ }
489
534
 
490
535
  // src-public/env.ts
491
536
  var crypto = __toESM(require("crypto"));
@@ -632,6 +677,7 @@ var AES256GCM = class {
632
677
  var env_default = EnvEngine;
633
678
 
634
679
  // src-public/pubsub.ts
680
+ var import_co_body = __toESM(require("co-body"));
635
681
  function isSubscriptionOptionsPush(opts) {
636
682
  return "endpointUrl" in opts;
637
683
  }
@@ -640,6 +686,60 @@ var PubSubHelper = class extends Runtime {
640
686
  super(opts);
641
687
  this.pubSub = pubSub;
642
688
  }
689
+ static async decodeMessageFromRequest(req) {
690
+ const rawMessage = await import_co_body.default.json(req);
691
+ const rawMessageText = Buffer.from(rawMessage.message?.data, "base64").toString("utf-8");
692
+ let messageBody;
693
+ try {
694
+ messageBody = JSON.parse(rawMessageText);
695
+ } catch (err) {
696
+ throw new Error("Could not parse the message body. Original body: " + rawMessageText + " . Error: " + err.message);
697
+ }
698
+ const message = {
699
+ sourceSystem: rawMessage.attributes?.source_system || "unknown",
700
+ targetSystem: rawMessage.attributes?.target_system || "*",
701
+ processStartedAt: parseDateOrDefault(rawMessage.attributes?.process_started_at),
702
+ recordModifiedAt: parseDateOrDefault(getEventTime(messageBody, rawMessage.attributes?.record_modified_at)),
703
+ originalPublishTime: parseDateOrDefault(rawMessage.attributes?.original_publish_time, parseDateOrDefault(rawMessage.publish_time)),
704
+ buildshipId: rawMessage.attributes?.buildship_id || "unknown",
705
+ publishTime: parseDateOrDefault(rawMessage.publish_time),
706
+ body: messageBody
707
+ };
708
+ return message;
709
+ }
710
+ async publish(options, payload, orgMessage) {
711
+ const topic = this.pubSub.topic(options.topicName, {
712
+ batching: {
713
+ maxMessages: 20,
714
+ maxMilliseconds: 2 * 1e3
715
+ }
716
+ });
717
+ let normPayloads = [];
718
+ if (!Array.isArray(payload)) {
719
+ normPayloads = [payload];
720
+ } else {
721
+ normPayloads = payload;
722
+ }
723
+ const promises = [];
724
+ for (let i = 0; i < normPayloads.length; i++) {
725
+ const normPayload = normPayloads[i];
726
+ promises.push((async () => {
727
+ const result = await topic.publishMessage({
728
+ data: Buffer.from(JSON.stringify(normPayload)),
729
+ attributes: {
730
+ source_system: options.sourceSystem,
731
+ target_system: options.targetSystem || orgMessage?.targetSystem || "*",
732
+ process_started_at: (options.processStartedAt || orgMessage?.processStartedAt || /* @__PURE__ */ new Date()).toISOString(),
733
+ record_modified_at: (getEventTime(normPayload, null) || /* @__PURE__ */ new Date()).toISOString(),
734
+ original_publish_time: (orgMessage?.originalPublishTime || orgMessage?.publishTime || /* @__PURE__ */ new Date())?.toDateString() || "",
735
+ buildship_id: this.systemEnvName + "-" + this.workflowId + "-" + this.triggerId
736
+ }
737
+ });
738
+ return result;
739
+ })());
740
+ }
741
+ return Promise.all(promises);
742
+ }
643
743
  async createOrUpdate(opts) {
644
744
  const subscriptionName = `${this.envName === "prod" ? "" : `${this.envName}---`}${this.triggerId}`;
645
745
  const topic = await this.ensureTopicExists(opts.topicName);
package/dist/package.json CHANGED
@@ -8,6 +8,7 @@
8
8
  "@hackylabs/deep-redact": "^2.2.1",
9
9
  "ajv": "^8.17.1",
10
10
  "ajv-formats": "^3.0.1",
11
+ "co-body": "^6.2.0",
11
12
  "jose": "^6.0.11",
12
13
  "lodash.clonedeep": "^4.5.0"
13
14
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shushed/helpers",
3
- "version": "0.0.28",
3
+ "version": "0.0.30",
4
4
  "author": "",
5
5
  "license": "UNLICENSED",
6
6
  "description": "",
@@ -8,6 +8,7 @@
8
8
  "@hackylabs/deep-redact": "^2.2.1",
9
9
  "ajv": "^8.17.1",
10
10
  "ajv-formats": "^3.0.1",
11
+ "co-body": "^6.2.0",
11
12
  "jose": "^6.0.11",
12
13
  "lodash.clonedeep": "^4.5.0"
13
14
  },