@shushed/helpers 0.0.227-main-20260107094010 → 0.0.227

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.
Files changed (41) hide show
  1. package/dist/cjs/contracts/index.js +5 -1
  2. package/dist/cjs/contracts/product-draft.schema.json +159 -5
  3. package/dist/cjs/contracts/purchase-orderline.schema.json +135 -0
  4. package/dist/cjs/contracts/stock-movement.schema.json +144 -0
  5. package/dist/cjs/dist-dereferenced/index.js +5 -1
  6. package/dist/cjs/dist-dereferenced/messages/product-draft.js +1 -1
  7. package/dist/cjs/dist-dereferenced/product-draft.js +1 -1
  8. package/dist/cjs/dist-dereferenced/purchase-orderline.js +4 -0
  9. package/dist/cjs/dist-dereferenced/stock-movement.js +4 -0
  10. package/dist/cjs/dist-types/purchase-orderline.js +2 -0
  11. package/dist/cjs/dist-types/stock-movement.js +2 -0
  12. package/dist/cjs/src-public/airtable.js +96 -59
  13. package/dist/cjs/src-public/centra.js +56 -5
  14. package/dist/cjs/src-public/env.js +1 -1
  15. package/dist/cjs/src-public/index.js +3 -1
  16. package/dist/cjs/src-public/pubsub.js +35 -10
  17. package/dist/cjs/src-public/runtime.js +48 -9
  18. package/dist/cjs/src-public/sitoo.js +349 -0
  19. package/dist/cjs/src-public/utils.js +3 -0
  20. package/dist/package.json +3 -2
  21. package/dist/types/contracts/index.d.ts +2 -0
  22. package/dist/types/dist-dereferenced/index.d.ts +2 -0
  23. package/dist/types/dist-dereferenced/messages/product-draft.d.ts +148 -1
  24. package/dist/types/dist-dereferenced/product-draft.d.ts +148 -1
  25. package/dist/types/dist-dereferenced/purchase-orderline.d.ts +114 -0
  26. package/dist/types/dist-dereferenced/stock-movement.d.ts +110 -0
  27. package/dist/types/dist-types/index.d.ts +2 -0
  28. package/dist/types/dist-types/messages/product-draft.d.ts +23 -4
  29. package/dist/types/dist-types/product-draft.d.ts +23 -4
  30. package/dist/types/dist-types/purchase-orderline.d.ts +31 -0
  31. package/dist/types/dist-types/stock-movement.d.ts +30 -0
  32. package/dist/types/src-public/airtable.d.ts +0 -9
  33. package/dist/types/src-public/centra.d.ts +3 -0
  34. package/dist/types/src-public/env.d.ts +1 -1
  35. package/dist/types/src-public/index.d.ts +1 -0
  36. package/dist/types/src-public/pubsub.d.ts +4 -1
  37. package/dist/types/src-public/runtime.d.ts +17 -4
  38. package/dist/types/src-public/sitoo.d.ts +254 -0
  39. package/dist/types/src-public/types.d.ts +6 -0
  40. package/dist/types/src-public/utils.d.ts +1 -1
  41. package/package.json +4 -3
@@ -42,71 +42,107 @@ class AirtableHelper extends runtime_1.default {
42
42
  }
43
43
  return existingRecord;
44
44
  }
45
- async updateMultiple(payload, options = {}, callIdx = 0, collectedResult = {
46
- updatedRecords: [],
47
- createdRecords: [],
48
- records: []
49
- }) {
45
+ async updateMultiple(payload, options = {}) {
50
46
  let response = null;
51
47
  const tableUrl = `https://api.airtable.com/v0/${this.baseId}/${this.tableId}`;
52
- const currentBatch = payload.slice(callIdx * 10, (callIdx + 1) * 10);
53
- try {
54
- response = await fetch(`${tableUrl}`, {
55
- method: "PATCH",
56
- headers: {
57
- Authorization: `Bearer ${this.apiKey}`,
58
- "Content-Type": "application/json",
59
- },
60
- body: JSON.stringify({
61
- performUpsert: {
62
- fieldsToMergeOn: (options.fieldsToMergeOn ?? [this.primaryKeyFieldName]).map(x => this.dictionary[x] || x),
63
- },
64
- returnFieldsByFieldId: true,
65
- typecast: options.typecast || false,
66
- records: currentBatch.map(x => {
67
- const recordId = x.$recordId;
68
- const fieldsWithoutRecordId = { ...x };
69
- delete fieldsWithoutRecordId.$recordId;
70
- const record = {
71
- fields: AirtableHelper.convertToDictionary(this.dictionary, this.primaryKeyWritable === false
72
- ? AirtableHelper.removePrimaryKey(fieldsWithoutRecordId, this.primaryKeyFieldName)
73
- : fieldsWithoutRecordId),
74
- };
75
- if (recordId) {
76
- record.id = recordId;
77
- }
78
- return record;
79
- })
80
- }),
48
+ const batchSize = 10;
49
+ let collectedResult = {
50
+ updatedRecords: [],
51
+ createdRecords: [],
52
+ records: []
53
+ };
54
+ const fieldsToMergeOn = (options.fieldsToMergeOn || [this.primaryKeyFieldName]);
55
+ const fieldsToMergeOnIds = fieldsToMergeOn.map(x => this.dictionary[x] || x);
56
+ let callIdx = 0;
57
+ const payloadDeduplicated = payload.filter((x, idx, self) => idx === self.findIndex((t) => fieldsToMergeOn.every(field => (0, lodash_isequal_1.default)(t[field], x[field]))));
58
+ const maxCallIdx = Math.ceil(payloadDeduplicated.length / batchSize);
59
+ while (callIdx < maxCallIdx) {
60
+ const currentBatch = payloadDeduplicated.slice(callIdx * batchSize, (callIdx + 1) * batchSize);
61
+ const recordsInBatch = currentBatch.map(x => {
62
+ const recordId = x.$recordId;
63
+ const fieldsWithoutRecordId = { ...x };
64
+ delete fieldsWithoutRecordId.$recordId;
65
+ const record = {
66
+ fields: AirtableHelper.convertToDictionary(this.dictionary, this.primaryKeyWritable === false
67
+ ? AirtableHelper.removePrimaryKey(fieldsWithoutRecordId, this.primaryKeyFieldName)
68
+ : fieldsWithoutRecordId),
69
+ };
70
+ if (recordId) {
71
+ record.id = recordId;
72
+ }
73
+ return record;
81
74
  });
82
- if (!response.ok && response) {
83
- const text = await response.text().catch(() => `${response?.status || 'unknown'}`);
84
- throw new Error(text);
75
+ try {
76
+ response = await fetch(`${tableUrl}`, {
77
+ method: "PATCH",
78
+ headers: {
79
+ Authorization: `Bearer ${this.apiKey}`,
80
+ "Content-Type": "application/json",
81
+ },
82
+ body: JSON.stringify({
83
+ performUpsert: {
84
+ fieldsToMergeOn: fieldsToMergeOnIds,
85
+ },
86
+ returnFieldsByFieldId: true,
87
+ typecast: options.typecast || false,
88
+ records: recordsInBatch
89
+ }),
90
+ });
91
+ if (!response.ok && response) {
92
+ const text = await response.text().catch(() => `${response?.status || 'unknown'}`);
93
+ throw new Error(text);
94
+ }
95
+ const resp = (await response.json());
96
+ collectedResult = {
97
+ updatedRecords: collectedResult.updatedRecords.concat(resp.updatedRecords),
98
+ createdRecords: collectedResult.createdRecords.concat(resp.createdRecords),
99
+ records: collectedResult.records.concat(resp.records.map(x => AirtableHelper.translateFields(this.dictionary, x)))
100
+ };
85
101
  }
86
- const resp = (await response.json());
87
- const nextCollectedResult = {
88
- updatedRecords: collectedResult.updatedRecords.concat(resp.updatedRecords),
89
- createdRecords: collectedResult.createdRecords.concat(resp.createdRecords),
90
- records: collectedResult.records.concat(resp.records.map(x => AirtableHelper.translateFields(this.dictionary, x)))
91
- };
92
- if (payload.length > (callIdx + 1) * 10) {
93
- return this.updateMultiple(payload, options, callIdx + 1, nextCollectedResult);
102
+ catch (err) {
103
+ const errorMessage = `Failed to update records in ${this.tableId} table (baseId: ${this.baseId}). Status: ${response?.status || 'unknown'}. Error: ${err.message}`;
104
+ const batchErrors = currentBatch.map(() => new Error(errorMessage));
105
+ collectedResult = {
106
+ updatedRecords: collectedResult.updatedRecords,
107
+ createdRecords: collectedResult.createdRecords,
108
+ records: collectedResult.records.concat(batchErrors)
109
+ };
110
+ }
111
+ finally {
112
+ callIdx += 1;
94
113
  }
95
- return nextCollectedResult;
96
114
  }
97
- catch (err) {
98
- const errorMessage = `Failed to update records in ${this.tableId} table (baseId: ${this.baseId}). Status: ${response?.status || 'unknown'}. Error: ${err.message}`;
99
- const batchErrors = currentBatch.map(() => new Error(errorMessage));
100
- const nextCollectedResult = {
101
- updatedRecords: collectedResult.updatedRecords,
102
- createdRecords: collectedResult.createdRecords,
103
- records: collectedResult.records.concat(batchErrors)
104
- };
105
- if (payload.length > (callIdx + 1) * 10) {
106
- return this.updateMultiple(payload, options, callIdx + 1, nextCollectedResult);
115
+ const resultInOrder = [];
116
+ for (let i = 0; i < payload.length; i++) {
117
+ let j = 0;
118
+ let foundMatchingRecord = null;
119
+ while (j < collectedResult.records.length && foundMatchingRecord === null) {
120
+ let isMatching = true;
121
+ let k = 0;
122
+ while (k < fieldsToMergeOn.length && isMatching) {
123
+ const field = fieldsToMergeOn[k];
124
+ if (!(0, lodash_isequal_1.default)(collectedResult.records[j].fields[field], payload[i][field])) {
125
+ isMatching = false;
126
+ }
127
+ k += 1;
128
+ }
129
+ if (isMatching) {
130
+ foundMatchingRecord = j;
131
+ }
132
+ j += 1;
133
+ }
134
+ if (foundMatchingRecord !== null) {
135
+ resultInOrder.push(collectedResult.records[foundMatchingRecord]);
136
+ }
137
+ else {
138
+ resultInOrder.push(new Error(`Record ${payload[i][this.primaryKeyFieldName]} does not match any record in the response`));
107
139
  }
108
- return nextCollectedResult;
109
140
  }
141
+ return {
142
+ updatedRecords: collectedResult.updatedRecords,
143
+ createdRecords: collectedResult.createdRecords,
144
+ records: resultInOrder
145
+ };
110
146
  }
111
147
  async upsert(payload) {
112
148
  const existingRecord = await this.getExistingRecord(payload);
@@ -258,9 +294,10 @@ class AirtableHelper extends runtime_1.default {
258
294
  const escapeFormulaValue = (value) => {
259
295
  return value.replace(/"/g, '\\"');
260
296
  };
297
+ const dedupedKeys = keys.filter((x, idx, self) => self.indexOf(x) === idx);
261
298
  const batchSize = 50;
262
- for (let i = 0; i < keys.length; i += batchSize) {
263
- const batch = keys.slice(i, i + batchSize);
299
+ for (let i = 0; i < dedupedKeys.length; i += batchSize) {
300
+ const batch = dedupedKeys.slice(i, i + batchSize);
264
301
  const orConditions = batch.map(key => `${this.dictionary[this.primaryKeyFieldName]} = "${escapeFormulaValue(key)}"`).join(', ');
265
302
  const formula = `OR(${orConditions})`;
266
303
  const records = await this.getExistingRecords(formula);
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const crypto_1 = __importDefault(require("crypto"));
7
7
  const env_1 = __importDefault(require("./env"));
8
8
  const utils_1 = require("./utils");
9
- const CACHE_EXPIRATION_MS = 1000 * 60 * 60 * 3;
9
+ const CACHE_EXPIRATION_MS = 1000 * 60 * 5;
10
10
  class CentraHelper extends env_1.default {
11
11
  opts;
12
12
  shaToken;
@@ -99,6 +99,12 @@ class CentraHelper extends env_1.default {
99
99
  getCacheKeyForMarket(marketExternalId) {
100
100
  return `${this.getCacheKeyForMarkets()}_${marketExternalId}`;
101
101
  }
102
+ getCacheKeyForCampaigns() {
103
+ return `centra_${this.shaToken}_campaign_name`;
104
+ }
105
+ getCacheKeyForCampaign(campaignName) {
106
+ return `${this.getCacheKeyForCampaigns()}_${campaignName}`;
107
+ }
102
108
  getCacheKeyForSizeCharts() {
103
109
  return `centra_${this.shaToken}_size_chart_external_id`;
104
110
  }
@@ -130,7 +136,7 @@ class CentraHelper extends env_1.default {
130
136
  return `${this.getCacheKeyForCentraWarehouses()}_${warehouseExternalId}`;
131
137
  }
132
138
  getCacheKeyForCentraPricelists() {
133
- return `centra_${this.shaToken}_pricelist_external_id`;
139
+ return `centra_${this.shaToken}_pricelists_external_id`;
134
140
  }
135
141
  getCacheKeyForCentraPricelist(pricelistExternalId) {
136
142
  return `${this.getCacheKeyForCentraPricelists()}_${pricelistExternalId}`;
@@ -218,7 +224,7 @@ class CentraHelper extends env_1.default {
218
224
  return result;
219
225
  }
220
226
  async fetchCentraCampaigns(names) {
221
- const limit = (names?.length || 0) > 200 ? 200 : (names?.length || 0);
227
+ const limit = names ? (names.length > 200 ? 200 : names.length) : 200;
222
228
  let nextCursor = null;
223
229
  const result = {};
224
230
  do {
@@ -270,7 +276,7 @@ class CentraHelper extends env_1.default {
270
276
  nextCursor = null;
271
277
  }
272
278
  if (campaignConnection && campaignConnection.edges?.length) {
273
- for (let i = campaignConnection.edges.length; i < (names?.length || 0); i++) {
279
+ for (let i = 0; i < campaignConnection.edges.length; i++) {
274
280
  const { node } = campaignConnection.edges[i];
275
281
  result[node.name] = node;
276
282
  }
@@ -721,7 +727,9 @@ class CentraHelper extends env_1.default {
721
727
  }
722
728
  else {
723
729
  for (const warehouse of warehouses) {
724
- warehouseToSet[warehouse.externalId] = warehouse;
730
+ if (warehouse.externalId) {
731
+ warehouseToSet[warehouse.externalId] = warehouse;
732
+ }
725
733
  }
726
734
  await this.set(Object.entries(warehouseToSet).filter(([_, value]) => !(value instanceof Error)).map(([key, value]) => ({ name: this.getCacheKeyForCentraWarehouse(key), value: JSON.stringify(value) })), 'env', {
727
735
  ephemeralMs: CACHE_EXPIRATION_MS,
@@ -797,6 +805,49 @@ class CentraHelper extends env_1.default {
797
805
  }
798
806
  return Object.assign({}, pricelistInCache, pricelistToSet);
799
807
  }
808
+ async getCentraCampaigns(alwaysFetch = false) {
809
+ let campaignInCache = {};
810
+ let dedupedCampaignNamesInCache = [];
811
+ let campaignsToFetch = null;
812
+ if (!alwaysFetch) {
813
+ const campaignNamesInCache = await (this.get(this.getCacheKeyForCampaigns(), 'env', {
814
+ isEphemeral: true,
815
+ encrypted: false,
816
+ }).then(x => x ? JSON.parse(x) : null));
817
+ if (campaignNamesInCache) {
818
+ dedupedCampaignNamesInCache = campaignNamesInCache.filter((x, index, self) => self.indexOf(x) === index);
819
+ campaignInCache = Object.fromEntries(Object.entries(await this.get(dedupedCampaignNamesInCache.map((x) => this.getCacheKeyForCampaign(x)), 'env', {
820
+ isEphemeral: true,
821
+ encrypted: false,
822
+ })).map(([key, value]) => [key, value ? JSON.parse(value || 'null') : undefined]).filter(([_, value]) => value));
823
+ campaignsToFetch = dedupedCampaignNamesInCache.filter(x => !campaignInCache[x]);
824
+ }
825
+ }
826
+ const campaignToSet = {};
827
+ if (!campaignsToFetch || campaignsToFetch.length) {
828
+ const campaigns = await this.fetchCentraCampaigns();
829
+ if (CentraHelper.isCentraErrors(campaigns)) {
830
+ return new Error(`Failed to fetch campaigns: ${campaigns.errors.map((x) => x.message).join(', ')}`);
831
+ }
832
+ else {
833
+ for (const campaign of Object.values(campaigns)) {
834
+ campaignToSet[campaign.name] = campaign;
835
+ }
836
+ await this.set(Object.entries(campaignToSet).filter(([_, value]) => !(value instanceof Error)).map(([key, value]) => ({ name: this.getCacheKeyForCampaign(key), value: JSON.stringify(value) })), 'env', {
837
+ ephemeralMs: CACHE_EXPIRATION_MS,
838
+ encrypted: false,
839
+ });
840
+ await this.set([{
841
+ name: this.getCacheKeyForCampaigns(),
842
+ value: JSON.stringify(Object.keys(campaignToSet)),
843
+ }], 'env', {
844
+ ephemeralMs: CACHE_EXPIRATION_MS,
845
+ encrypted: false,
846
+ });
847
+ }
848
+ }
849
+ return Object.assign({}, campaignInCache, campaignToSet);
850
+ }
800
851
  async getCentraMarkets(alwaysFetch = false) {
801
852
  let marketInCache = {};
802
853
  let dedupedMarketNamesInCache = [];
@@ -567,7 +567,7 @@ class EnvEngine extends runtime_1.default {
567
567
  batchSize: 1,
568
568
  subscriptionFilter: null,
569
569
  batchWindowSeconds: 10,
570
- }, Object.fromEntries(Object.entries(rnPartialConfig).filter(x => !(x === null || x === undefined))));
570
+ }, Object.fromEntries(Object.entries(rnPartialConfig).filter(([x]) => !(x === null || x === undefined))));
571
571
  return rnConfig;
572
572
  }
573
573
  createOrUpdateRespectfulNudge(subscriptionName, rnPartialConfig) {
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
17
17
  return (mod && mod.__esModule) ? mod : { "default": mod };
18
18
  };
19
19
  Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.RedisConnectionError = exports.RateLimit = exports.setHeaders = exports.BCOrderHelper = exports.DatoHelper = exports.AirtableHelper = exports.CentraHelper = exports.BigQueryHelper = exports.JWKSHelper = exports.CloudTasksHelper = exports.Secrets = exports.SchedulerHelper = exports.Logging = exports.Runtime = exports.PubSubHelper = exports.EnvEngine = exports.validate = void 0;
20
+ exports.SitooHelper = exports.RedisConnectionError = exports.RateLimit = exports.setHeaders = exports.BCOrderHelper = exports.DatoHelper = exports.AirtableHelper = exports.CentraHelper = exports.BigQueryHelper = exports.JWKSHelper = exports.CloudTasksHelper = exports.Secrets = exports.SchedulerHelper = exports.Logging = exports.Runtime = exports.PubSubHelper = exports.EnvEngine = exports.validate = void 0;
21
21
  var validate_1 = require("./validate");
22
22
  Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return __importDefault(validate_1).default; } });
23
23
  __exportStar(require("./sanitize"), exports);
@@ -52,3 +52,5 @@ Object.defineProperty(exports, "setHeaders", { enumerable: true, get: function (
52
52
  var rateLimit_1 = require("./rateLimit");
53
53
  Object.defineProperty(exports, "RateLimit", { enumerable: true, get: function () { return __importDefault(rateLimit_1).default; } });
54
54
  Object.defineProperty(exports, "RedisConnectionError", { enumerable: true, get: function () { return rateLimit_1.RedisConnectionError; } });
55
+ var sitoo_1 = require("./sitoo");
56
+ Object.defineProperty(exports, "SitooHelper", { enumerable: true, get: function () { return __importDefault(sitoo_1).default; } });
@@ -79,19 +79,44 @@ class PubSubHelper extends runtime_1.default {
79
79
  }
80
80
  const topic = pubSubPublishTopics[options.topicName];
81
81
  const batches = payloads.length > 5 ? (0, lodash_chunk_1.default)(payloads, 10) : [payloads];
82
- const attributes = {
83
- ...options.extraAttributes,
84
- source_system: options.sourceSystem,
85
- target_system: options.targetSystem,
86
- buildship_id: this.systemEnvName + '-' + this.workflowId + '-' + this.triggerId,
87
- };
82
+ let nextAttributes = {};
88
83
  const messageIds = [];
89
84
  for (let i = 0; i < batches.length; i++) {
90
85
  const batch = batches[i];
91
- const results = await Promise.allSettled(batch.map((x) => topic.publishMessage({
92
- data: Buffer.from(JSON.stringify(x)),
93
- attributes: Object.fromEntries(Object.entries(options.attributesGenerator ? Object.assign({}, attributes, options.attributesGenerator(x)) : attributes).filter(([_, v]) => v !== undefined && v !== null).map(([k, v]) => [k, `${v}`]))
94
- })));
86
+ const results = await Promise.allSettled(batch.map((x) => {
87
+ if (options.attributesGenerator) {
88
+ nextAttributes = Object.fromEntries(Object.entries(options.attributesGenerator(x)).filter(([_, v]) => v !== undefined && v !== null).map(([k, v]) => [k, typeof v === 'boolean' ? (v ? 'yes' : 'no') : `${v}`]));
89
+ }
90
+ if (typeof options.extraAttributes === 'function') {
91
+ nextAttributes = Object.fromEntries(Object.entries(options.extraAttributes ? Object.assign({}, nextAttributes, options.extraAttributes(x)) : nextAttributes).filter(([_, v]) => v !== undefined && v !== null).map(([k, v]) => [k, typeof v === 'boolean' ? (v ? 'yes' : 'no') : `${v}`]));
92
+ }
93
+ else if (typeof options.extraAttributes === 'object') {
94
+ for (const key in options.extraAttributes) {
95
+ let resultForKey;
96
+ if (typeof options.extraAttributes[key] === 'function') {
97
+ resultForKey = options.extraAttributes[key](x);
98
+ }
99
+ else {
100
+ resultForKey = options.extraAttributes[key];
101
+ }
102
+ if (typeof resultForKey === 'boolean') {
103
+ nextAttributes[key] = resultForKey ? 'yes' : 'no';
104
+ }
105
+ else {
106
+ nextAttributes[key] = `${resultForKey}`;
107
+ }
108
+ }
109
+ nextAttributes = Object.assign(nextAttributes, {
110
+ source_system: options.sourceSystem,
111
+ target_system: options.targetSystem,
112
+ buildship_id: this.systemEnvName + '-' + this.workflowId + '-' + this.triggerId,
113
+ });
114
+ }
115
+ return topic.publishMessage({
116
+ data: Buffer.from(JSON.stringify(x)),
117
+ attributes: nextAttributes
118
+ });
119
+ }));
95
120
  for (const result of results) {
96
121
  if (result.status === 'fulfilled') {
97
122
  messageIds.push(result.value);
@@ -1,6 +1,10 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.Logging = void 0;
7
+ const lodash_pick_1 = __importDefault(require("lodash.pick"));
4
8
  const DEFAULT_BRANCH = 'migratedprod';
5
9
  const getCircularReplacer = () => {
6
10
  const seen = new WeakSet();
@@ -59,34 +63,50 @@ exports.Logging = Logging;
59
63
  class Runtime {
60
64
  workflowId;
61
65
  triggerId;
66
+ triggerName;
67
+ triggerVersion;
62
68
  envName;
63
69
  pubSubPrefix;
64
70
  systemEnvName;
65
71
  runtimeUrl;
66
72
  logging;
67
- workflowRoot = null;
73
+ triggerDataProperties = undefined;
74
+ triggerConfigProperties = undefined;
75
+ triggerConfig = undefined;
76
+ workflowRoot;
68
77
  constructor(opts) {
69
78
  if (opts instanceof Runtime) {
70
79
  this.workflowRoot = opts.workflowRoot;
71
80
  this.workflowId = opts.workflowId;
72
81
  this.triggerId = opts.triggerId;
82
+ this.triggerName = opts.triggerName;
83
+ this.triggerVersion = opts.triggerVersion;
73
84
  this.systemEnvName = opts.systemEnvName;
74
85
  this.runtimeUrl = opts.runtimeUrl;
75
86
  this.pubSubPrefix = opts.pubSubPrefix;
76
87
  this.envName = opts.envName;
77
88
  this.logging = opts.logging || new Logging(this.workflowId, this.triggerId, this.systemEnvName);
89
+ this.triggerName = opts.triggerName;
90
+ this.triggerVersion = opts.triggerVersion;
91
+ this.triggerDataProperties = opts.triggerDataProperties;
92
+ this.triggerConfigProperties = opts.triggerConfigProperties;
93
+ this.triggerConfig = opts.triggerConfig;
78
94
  }
79
95
  else {
80
- if (opts.root) {
81
- this.workflowRoot = opts.root;
82
- }
96
+ this.workflowRoot = opts.root || {};
83
97
  this.workflowId = opts.workflowId || opts.workflow?.id || '';
84
- this.triggerId = opts.triggerId || opts.trigger?.id || '';
85
- if (!this.triggerId && opts.session) {
86
- this.triggerId = Object.values(opts.session?.executedNodes || {}).find(e => e.nodeType === 'trigger')?.nodeId ?? 'unknown';
98
+ if (opts.trigger?.label) {
99
+ this.triggerId = opts.trigger.id || '00000000-0000-0000-0000-000000000000';
100
+ this.triggerName = opts.trigger.label.split(/\sv\d/)[0].trim() || this.workflowId;
101
+ this.triggerVersion = buildSemver((opts.trigger.label.split(/\sv\d/)[1]?.trim() || 'v0').replace(/^v/, ''));
102
+ this.triggerDataProperties = opts.trigger.data?.properties;
103
+ this.triggerConfigProperties = opts.trigger.config?.properties;
87
104
  }
88
- else if (!this.triggerId) {
89
- this.triggerId = 'unknown';
105
+ else {
106
+ this.triggerId = Object.values(opts.session?.executedNodes || {}).find(e => e.nodeType === 'trigger')?.nodeId ?? '00000000-0000-0000-0000-000000000000';
107
+ this.triggerName = this.workflowRoot[this.triggerId]?.triggerName || this.workflowId;
108
+ this.triggerVersion = this.workflowRoot[this.triggerId]?.triggerVersion || '0.0.0';
109
+ this.triggerConfig = this.workflowRoot[this.triggerId]?.triggerConfig;
90
110
  }
91
111
  this.systemEnvName = this.getSystemEnvName(opts);
92
112
  this.envName = this.systemEnvName === DEFAULT_BRANCH ? 'prod' : this.systemEnvName;
@@ -95,6 +115,18 @@ class Runtime {
95
115
  this.logging = opts.logging || new Logging(this.workflowId, this.triggerId, this.systemEnvName);
96
116
  }
97
117
  }
118
+ enhanceWorkflowReturn(triggerReturn, triggerConfig) {
119
+ const keys = Object.keys(this.triggerDataProperties || {});
120
+ return Object.assign((0, lodash_pick_1.default)({
121
+ workflowId: this.workflowId,
122
+ triggerId: this.triggerId,
123
+ triggerName: this.triggerName,
124
+ triggerVersion: this.triggerVersion,
125
+ systemEnvName: this.systemEnvName,
126
+ envName: this.envName,
127
+ triggerConfig: (0, lodash_pick_1.default)(triggerConfig, Object.entries(this.triggerConfigProperties || {}).filter(([_, value]) => !value.buildship?.sensitive).map(([key]) => key))
128
+ }, keys), triggerReturn);
129
+ }
98
130
  getRuntimeUrl(options) {
99
131
  if (options.runtimeUrl && this.isDeployment) {
100
132
  return options.runtimeUrl;
@@ -143,3 +175,10 @@ class Runtime {
143
175
  }
144
176
  exports.default = Runtime;
145
177
  ;
178
+ function buildSemver(version) {
179
+ const parts = version.split(/\./).map(x => parseInt(x, 10));
180
+ for (let i = parts.length; i < 3; i++) {
181
+ parts.push(0);
182
+ }
183
+ return parts.join('.');
184
+ }