@shushed/helpers 0.0.197 → 0.0.198-v2-20251104135028

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 (234) hide show
  1. package/dist/cjs/dist-dereferenced/asset.js +4 -0
  2. package/dist/cjs/dist-dereferenced/category.js +4 -0
  3. package/dist/cjs/dist-dereferenced/country.js +4 -0
  4. package/dist/cjs/dist-dereferenced/currency.js +4 -0
  5. package/dist/cjs/dist-dereferenced/customer-segment.js +4 -0
  6. package/dist/cjs/dist-dereferenced/development-colour.js +4 -0
  7. package/dist/cjs/dist-dereferenced/index.js +69 -0
  8. package/dist/cjs/dist-dereferenced/marketing-preferences.js +4 -0
  9. package/dist/cjs/dist-dereferenced/messages/ean-change.js +4 -0
  10. package/dist/cjs/dist-dereferenced/messages/index.js +50 -0
  11. package/dist/cjs/dist-dereferenced/messages/order/delivered.js +4 -0
  12. package/dist/cjs/dist-dereferenced/messages/order/index.js +18 -0
  13. package/dist/cjs/dist-dereferenced/messages/order/new.js +4 -0
  14. package/dist/cjs/dist-dereferenced/messages/order/processed.js +4 -0
  15. package/dist/cjs/dist-dereferenced/messages/order/return-initiated.js +4 -0
  16. package/dist/cjs/dist-dereferenced/messages/order/returned.js +4 -0
  17. package/dist/cjs/dist-dereferenced/messages/order/shipped.js +4 -0
  18. package/dist/cjs/dist-dereferenced/messages/price-change.js +4 -0
  19. package/dist/cjs/dist-dereferenced/messages/product-category.js +4 -0
  20. package/dist/cjs/dist-dereferenced/messages/product-draft.js +4 -0
  21. package/dist/cjs/dist-dereferenced/messages/product.js +4 -0
  22. package/dist/cjs/dist-dereferenced/money.js +4 -0
  23. package/dist/cjs/dist-dereferenced/order/address.js +4 -0
  24. package/dist/cjs/dist-dereferenced/order/customer.js +4 -0
  25. package/dist/cjs/dist-dereferenced/order/index.js +51 -0
  26. package/dist/cjs/dist-dereferenced/order/item.js +4 -0
  27. package/dist/cjs/dist-dereferenced/order/orderMain.js +4 -0
  28. package/dist/cjs/dist-dereferenced/order/payment.js +4 -0
  29. package/dist/cjs/dist-dereferenced/order/shipment/index.js +45 -0
  30. package/dist/cjs/dist-dereferenced/order/shipment/item/index.js +11 -0
  31. package/dist/cjs/dist-dereferenced/order/shipment/item/itemMain.js +4 -0
  32. package/dist/cjs/dist-dereferenced/order/shipment/item/returned.js +4 -0
  33. package/dist/cjs/dist-dereferenced/order/shipment/pos/index.js +13 -0
  34. package/dist/cjs/dist-dereferenced/order/shipment/pos/outbound.js +4 -0
  35. package/dist/cjs/dist-dereferenced/order/shipment/pos/posMain.js +4 -0
  36. package/dist/cjs/dist-dereferenced/order/shipment/pos/return.js +4 -0
  37. package/dist/cjs/dist-dereferenced/order/shipment/shipmentMain.js +4 -0
  38. package/dist/cjs/dist-dereferenced/order/shipment/shipped/index.js +13 -0
  39. package/dist/cjs/dist-dereferenced/order/shipment/shipped/outbound.js +4 -0
  40. package/dist/cjs/dist-dereferenced/order/shipment/shipped/return.js +4 -0
  41. package/dist/cjs/dist-dereferenced/order/shipment/shipped/shippedMain.js +4 -0
  42. package/dist/cjs/dist-dereferenced/price.js +4 -0
  43. package/dist/cjs/dist-dereferenced/product-category.js +4 -0
  44. package/dist/cjs/dist-dereferenced/product-draft.js +4 -0
  45. package/dist/cjs/dist-dereferenced/product.js +4 -0
  46. package/dist/cjs/dist-dereferenced/stock.js +4 -0
  47. package/dist/cjs/dist-dereferenced/total.js +4 -0
  48. package/dist/cjs/dist-types/asset.js +2 -0
  49. package/dist/cjs/dist-types/category.js +2 -0
  50. package/dist/cjs/dist-types/country.js +2 -0
  51. package/dist/cjs/dist-types/currency.js +2 -0
  52. package/dist/cjs/dist-types/customer-segment.js +2 -0
  53. package/dist/cjs/dist-types/development-colour.js +2 -0
  54. package/dist/cjs/dist-types/index.js +38 -0
  55. package/dist/cjs/dist-types/marketing-preferences.js +2 -0
  56. package/dist/cjs/dist-types/messages/ean-change.js +2 -0
  57. package/dist/cjs/dist-types/messages/index.js +37 -0
  58. package/dist/cjs/dist-types/messages/order/delivered.js +2 -0
  59. package/dist/cjs/dist-types/messages/order/index.js +2 -0
  60. package/dist/cjs/dist-types/messages/order/new.js +2 -0
  61. package/dist/cjs/dist-types/messages/order/processed.js +2 -0
  62. package/dist/cjs/dist-types/messages/order/return-initiated.js +2 -0
  63. package/dist/cjs/dist-types/messages/order/returned.js +2 -0
  64. package/dist/cjs/dist-types/messages/order/shipped.js +2 -0
  65. package/dist/cjs/dist-types/messages/price-change.js +2 -0
  66. package/dist/cjs/dist-types/messages/product-category.js +2 -0
  67. package/dist/cjs/dist-types/messages/product-draft.js +2 -0
  68. package/dist/cjs/dist-types/messages/product.js +2 -0
  69. package/dist/cjs/dist-types/money.js +2 -0
  70. package/dist/cjs/dist-types/order/address.js +2 -0
  71. package/dist/cjs/dist-types/order/customer.js +2 -0
  72. package/dist/cjs/dist-types/order/index.js +37 -0
  73. package/dist/cjs/dist-types/order/item.js +2 -0
  74. package/dist/cjs/dist-types/order/orderMain.js +2 -0
  75. package/dist/cjs/dist-types/order/payment.js +2 -0
  76. package/dist/cjs/dist-types/order/shipment/index.js +39 -0
  77. package/dist/cjs/dist-types/order/shipment/item/index.js +2 -0
  78. package/dist/cjs/dist-types/order/shipment/item/itemMain.js +2 -0
  79. package/dist/cjs/dist-types/order/shipment/item/returned.js +2 -0
  80. package/dist/cjs/dist-types/order/shipment/pos/index.js +2 -0
  81. package/dist/cjs/dist-types/order/shipment/pos/outbound.js +2 -0
  82. package/dist/cjs/dist-types/order/shipment/pos/posMain.js +2 -0
  83. package/dist/cjs/dist-types/order/shipment/pos/return.js +2 -0
  84. package/dist/cjs/dist-types/order/shipment/shipmentMain.js +2 -0
  85. package/dist/cjs/dist-types/order/shipment/shipped/index.js +2 -0
  86. package/dist/cjs/dist-types/order/shipment/shipped/outbound.js +2 -0
  87. package/dist/cjs/dist-types/order/shipment/shipped/return.js +2 -0
  88. package/dist/cjs/dist-types/order/shipment/shipped/shippedMain.js +2 -0
  89. package/dist/cjs/dist-types/price.js +2 -0
  90. package/dist/cjs/dist-types/product-category.js +2 -0
  91. package/dist/cjs/dist-types/product-draft.js +2 -0
  92. package/dist/cjs/dist-types/product.js +2 -0
  93. package/dist/cjs/dist-types/stock.js +2 -0
  94. package/dist/cjs/dist-types/total.js +2 -0
  95. package/dist/cjs/index.js +39 -0
  96. package/dist/cjs/src-public/airtable.js +530 -0
  97. package/dist/cjs/src-public/bigquery.js +59 -0
  98. package/dist/cjs/src-public/cloudtasks.js +207 -0
  99. package/dist/cjs/src-public/dato.js +260 -0
  100. package/dist/cjs/src-public/env.js +902 -0
  101. package/dist/cjs/src-public/getEventTime.js +28 -0
  102. package/dist/cjs/src-public/index.js +50 -0
  103. package/dist/cjs/src-public/ipValidation.js +167 -0
  104. package/dist/cjs/src-public/jwks.js +108 -0
  105. package/dist/cjs/src-public/pubsub.js +446 -0
  106. package/dist/cjs/src-public/rateLimit.js +140 -0
  107. package/dist/cjs/src-public/redisClient.js +44 -0
  108. package/dist/cjs/src-public/runtime.js +119 -0
  109. package/dist/cjs/src-public/sanitize.js +25 -0
  110. package/dist/cjs/src-public/scheduler.js +247 -0
  111. package/dist/cjs/src-public/secret.js +16 -0
  112. package/dist/cjs/src-public/setHeaders.js +16 -0
  113. package/dist/cjs/src-public/types.js +2 -0
  114. package/dist/cjs/src-public/utils.js +286 -0
  115. package/dist/cjs/src-public/validate.js +40 -0
  116. package/dist/package.json +6 -3
  117. package/dist/types/dist-dereferenced/asset.d.ts +34 -0
  118. package/dist/types/dist-dereferenced/category.d.ts +58 -0
  119. package/dist/types/dist-dereferenced/country.d.ts +8 -0
  120. package/dist/types/dist-dereferenced/currency.d.ts +8 -0
  121. package/dist/types/dist-dereferenced/customer-segment.d.ts +26 -0
  122. package/dist/types/dist-dereferenced/development-colour.d.ts +97 -0
  123. package/dist/types/dist-dereferenced/index.d.ts +16 -0
  124. package/dist/types/dist-dereferenced/marketing-preferences.d.ts +31 -0
  125. package/dist/types/dist-dereferenced/messages/ean-change.d.ts +17 -0
  126. package/dist/types/dist-dereferenced/messages/index.d.ts +6 -0
  127. package/dist/types/dist-dereferenced/messages/order/delivered.d.ts +3414 -0
  128. package/dist/types/dist-dereferenced/messages/order/index.d.ts +6 -0
  129. package/dist/types/dist-dereferenced/messages/order/new.d.ts +3414 -0
  130. package/dist/types/dist-dereferenced/messages/order/processed.d.ts +3408 -0
  131. package/dist/types/dist-dereferenced/messages/order/return-initiated.d.ts +3414 -0
  132. package/dist/types/dist-dereferenced/messages/order/returned.d.ts +3413 -0
  133. package/dist/types/dist-dereferenced/messages/order/shipped.d.ts +3412 -0
  134. package/dist/types/dist-dereferenced/messages/price-change.d.ts +58 -0
  135. package/dist/types/dist-dereferenced/messages/product-category.d.ts +33 -0
  136. package/dist/types/dist-dereferenced/messages/product-draft.d.ts +589 -0
  137. package/dist/types/dist-dereferenced/messages/product.d.ts +628 -0
  138. package/dist/types/dist-dereferenced/money.d.ts +41 -0
  139. package/dist/types/dist-dereferenced/order/address.d.ts +98 -0
  140. package/dist/types/dist-dereferenced/order/customer.d.ts +309 -0
  141. package/dist/types/dist-dereferenced/order/index.d.ts +3404 -0
  142. package/dist/types/dist-dereferenced/order/item.d.ts +336 -0
  143. package/dist/types/dist-dereferenced/order/orderMain.d.ts +3399 -0
  144. package/dist/types/dist-dereferenced/order/payment.d.ts +94 -0
  145. package/dist/types/dist-dereferenced/order/shipment/index.d.ts +253 -0
  146. package/dist/types/dist-dereferenced/order/shipment/item/index.d.ts +19 -0
  147. package/dist/types/dist-dereferenced/order/shipment/item/itemMain.d.ts +18 -0
  148. package/dist/types/dist-dereferenced/order/shipment/item/returned.d.ts +34 -0
  149. package/dist/types/dist-dereferenced/order/shipment/pos/index.d.ts +282 -0
  150. package/dist/types/dist-dereferenced/order/shipment/pos/outbound.d.ts +320 -0
  151. package/dist/types/dist-dereferenced/order/shipment/pos/posMain.d.ts +280 -0
  152. package/dist/types/dist-dereferenced/order/shipment/pos/return.d.ts +331 -0
  153. package/dist/types/dist-dereferenced/order/shipment/shipmentMain.d.ts +250 -0
  154. package/dist/types/dist-dereferenced/order/shipment/shipped/index.d.ts +288 -0
  155. package/dist/types/dist-dereferenced/order/shipment/shipped/outbound.d.ts +286 -0
  156. package/dist/types/dist-dereferenced/order/shipment/shipped/return.d.ts +287 -0
  157. package/dist/types/dist-dereferenced/order/shipment/shipped/shippedMain.d.ts +286 -0
  158. package/dist/types/dist-dereferenced/price.d.ts +49 -0
  159. package/dist/types/dist-dereferenced/product-category.d.ts +24 -0
  160. package/dist/types/dist-dereferenced/product-draft.d.ts +580 -0
  161. package/dist/types/dist-dereferenced/product.d.ts +619 -0
  162. package/dist/types/dist-dereferenced/stock.d.ts +74 -0
  163. package/dist/types/dist-dereferenced/total.d.ts +172 -0
  164. package/dist/types/dist-types/asset.d.ts +9 -0
  165. package/dist/types/dist-types/category.d.ts +20 -0
  166. package/dist/types/dist-types/country.d.ts +2 -0
  167. package/dist/types/dist-types/currency.d.ts +2 -0
  168. package/dist/types/dist-types/customer-segment.d.ts +6 -0
  169. package/dist/types/dist-types/development-colour.d.ts +24 -0
  170. package/dist/types/dist-types/index.d.ts +16 -0
  171. package/dist/types/dist-types/marketing-preferences.d.ts +9 -0
  172. package/dist/types/dist-types/messages/ean-change.d.ts +5 -0
  173. package/dist/types/dist-types/messages/index.d.ts +6 -0
  174. package/dist/types/dist-types/messages/order/delivered.d.ts +292 -0
  175. package/dist/types/dist-types/messages/order/index.d.ts +6 -0
  176. package/dist/types/dist-types/messages/order/new.d.ts +292 -0
  177. package/dist/types/dist-types/messages/order/processed.d.ts +292 -0
  178. package/dist/types/dist-types/messages/order/return-initiated.d.ts +292 -0
  179. package/dist/types/dist-types/messages/order/returned.d.ts +293 -0
  180. package/dist/types/dist-types/messages/order/shipped.d.ts +293 -0
  181. package/dist/types/dist-types/messages/price-change.d.ts +15 -0
  182. package/dist/types/dist-types/messages/product-category.d.ts +7 -0
  183. package/dist/types/dist-types/messages/product-draft.d.ts +136 -0
  184. package/dist/types/dist-types/messages/product.d.ts +144 -0
  185. package/dist/types/dist-types/money.d.ts +11 -0
  186. package/dist/types/dist-types/order/address.d.ts +27 -0
  187. package/dist/types/dist-types/order/customer.d.ts +81 -0
  188. package/dist/types/dist-types/order/index.d.ts +8 -0
  189. package/dist/types/dist-types/order/item.d.ts +85 -0
  190. package/dist/types/dist-types/order/orderMain.d.ts +289 -0
  191. package/dist/types/dist-types/order/payment.d.ts +26 -0
  192. package/dist/types/dist-types/order/shipment/index.d.ts +6 -0
  193. package/dist/types/dist-types/order/shipment/item/index.d.ts +4 -0
  194. package/dist/types/dist-types/order/shipment/item/itemMain.d.ts +6 -0
  195. package/dist/types/dist-types/order/shipment/item/returned.d.ts +11 -0
  196. package/dist/types/dist-types/order/shipment/pos/index.d.ts +5 -0
  197. package/dist/types/dist-types/order/shipment/pos/outbound.d.ts +76 -0
  198. package/dist/types/dist-types/order/shipment/pos/posMain.d.ts +71 -0
  199. package/dist/types/dist-types/order/shipment/pos/return.d.ts +75 -0
  200. package/dist/types/dist-types/order/shipment/shipmentMain.d.ts +62 -0
  201. package/dist/types/dist-types/order/shipment/shipped/index.d.ts +5 -0
  202. package/dist/types/dist-types/order/shipment/shipped/outbound.d.ts +68 -0
  203. package/dist/types/dist-types/order/shipment/shipped/return.d.ts +68 -0
  204. package/dist/types/dist-types/order/shipment/shipped/shippedMain.d.ts +69 -0
  205. package/dist/types/dist-types/price.d.ts +14 -0
  206. package/dist/types/dist-types/product-category.d.ts +6 -0
  207. package/dist/types/dist-types/product-draft.d.ts +135 -0
  208. package/dist/types/dist-types/product.d.ts +143 -0
  209. package/dist/types/dist-types/stock.d.ts +19 -0
  210. package/dist/types/dist-types/total.d.ts +44 -0
  211. package/dist/types/index.d.ts +3 -0
  212. package/dist/types/src-public/airtable.d.ts +211 -0
  213. package/dist/types/src-public/bigquery.d.ts +17 -0
  214. package/dist/types/src-public/cloudtasks.d.ts +74 -0
  215. package/dist/types/src-public/dato.d.ts +55 -0
  216. package/dist/types/src-public/env.d.ts +144 -0
  217. package/dist/types/src-public/getEventTime.d.ts +1 -0
  218. package/dist/types/src-public/index.d.ts +16 -0
  219. package/dist/types/src-public/ipValidation.d.ts +15 -0
  220. package/dist/types/src-public/jwks.d.ts +15 -0
  221. package/dist/types/src-public/pubsub.d.ts +93 -0
  222. package/dist/types/src-public/rateLimit.d.ts +21 -0
  223. package/dist/types/src-public/redisClient.d.ts +6 -0
  224. package/dist/types/src-public/runtime.d.ts +46 -0
  225. package/dist/types/src-public/sanitize.d.ts +4 -0
  226. package/dist/types/src-public/scheduler.d.ts +71 -0
  227. package/dist/types/src-public/secret.d.ts +6 -0
  228. package/dist/types/src-public/setHeaders.d.ts +13 -0
  229. package/dist/types/src-public/types.d.ts +263 -0
  230. package/dist/types/src-public/utils.d.ts +51 -0
  231. package/dist/types/src-public/validate.d.ts +9 -0
  232. package/package.json +7 -4
  233. package/dist/index.d.ts +0 -34842
  234. package/dist/index.js +0 -110556
@@ -0,0 +1,286 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FUNCTION_EXPR_ERROR = exports.getIdentityToken = exports.getAccessToken = exports.parseDateOrDefault = exports.validateGoogleAuth = exports.isCloudTask = exports.isRespectfulNudge = exports.isCronMessage = exports.isPubSubRequest = void 0;
7
+ exports.getEventTime = getEventTime;
8
+ exports.shortHash = shortHash;
9
+ exports.slugify = slugify;
10
+ exports.getFirestore = getFirestore;
11
+ exports.createHandlerDecorator = createHandlerDecorator;
12
+ exports.getSecret = getSecret;
13
+ exports.splitTimeToArr = splitTimeToArr;
14
+ exports.minutesAgo = minutesAgo;
15
+ exports.setRetryAfterVariable = setRetryAfterVariable;
16
+ exports.createFunction = createFunction;
17
+ exports.onResponse = onResponse;
18
+ const crypto_1 = __importDefault(require("crypto"));
19
+ const firestore_1 = require("@google-cloud/firestore");
20
+ const jwks_1 = __importDefault(require("./jwks"));
21
+ const isPubSubRequest = (headers) => (headers['User-Agent'] || headers['user-agent'] || '') === 'CloudPubSub-Google'
22
+ || (headers['User-Agent'] || headers['user-agent'] || '').indexOf('APIs-Google') !== -1;
23
+ exports.isPubSubRequest = isPubSubRequest;
24
+ const isCronMessage = (headers) => (headers['User-Agent'] || headers['user-agent'] || '') === 'Google-Cloud-Scheduler';
25
+ exports.isCronMessage = isCronMessage;
26
+ const isRespectfulNudge = (headers) => (headers['User-Agent'] || headers['user-agent'] || '') === 'Respectful-Nudge';
27
+ exports.isRespectfulNudge = isRespectfulNudge;
28
+ const isCloudTask = (headers) => (headers['User-Agent'] || headers['user-agent'] || '').indexOf('CloudTasks-Google') !== -1
29
+ || (headers['User-Agent'] || headers['user-agent'] || '').indexOf('Google-Cloud-Tasks') !== -1;
30
+ exports.isCloudTask = isCloudTask;
31
+ const validateGoogleAuth = async (opts, headers, firestore) => {
32
+ const token = headers.authorization?.split(" ")[1];
33
+ if (!token) {
34
+ throw new Error("Missing authorization header or invalid format, needs to be in format: Bearer <IdToken>");
35
+ }
36
+ let result;
37
+ try {
38
+ const jwksHelper = new jwks_1.default(opts, firestore);
39
+ result = await jwksHelper.validateAuthorizationHeader(token, opts.serviceAccount);
40
+ }
41
+ catch (err) {
42
+ throw new Error('Invalid authorization header ' + err.message);
43
+ }
44
+ return result;
45
+ };
46
+ exports.validateGoogleAuth = validateGoogleAuth;
47
+ const parseDateOrDefault = (date, defaultValue = null) => {
48
+ if (!date) {
49
+ return defaultValue;
50
+ }
51
+ if (date instanceof Date) {
52
+ if (isNaN(date.getTime())) {
53
+ return defaultValue;
54
+ }
55
+ return date;
56
+ }
57
+ const dateObj = new Date(date);
58
+ if (isNaN(dateObj.getTime())) {
59
+ return defaultValue;
60
+ }
61
+ return dateObj;
62
+ };
63
+ exports.parseDateOrDefault = parseDateOrDefault;
64
+ function getEventTime(x, defaultValue) {
65
+ const possibleKeys = [
66
+ 'last_modified_date_time',
67
+ 'record_modified_at',
68
+ 'last_modified_date',
69
+ 'last_modified_datetime',
70
+ 'last_modified_date_time',
71
+ 'lastModifiedDateTime',
72
+ 'lastModifiedAt',
73
+ 'last_modified_at',
74
+ 'SystemModifiedAt',
75
+ 'system_modified_at',
76
+ 'lastUpdatedAt',
77
+ 'modified_at',
78
+ 'last_updated_at',
79
+ 'modifiedAt',
80
+ ];
81
+ for (let i = 0; i < possibleKeys.length; i++) {
82
+ if (x[possibleKeys[i]]) {
83
+ const possibleDateTime = new Date(x[possibleKeys[i]]);
84
+ if (!isNaN(possibleDateTime.getTime())) {
85
+ return possibleDateTime;
86
+ }
87
+ }
88
+ }
89
+ return defaultValue;
90
+ }
91
+ function shortHash(input) {
92
+ const hash = crypto_1.default.createHash('sha256').update(input).digest();
93
+ const base64 = hash.toString('base64')
94
+ .replace(/\+/g, '-')
95
+ .replace(/\//g, '_')
96
+ .replace(/=+$/, '');
97
+ return base64.substring(0, 8);
98
+ }
99
+ function slugify(input) {
100
+ return input
101
+ .toLowerCase()
102
+ .replace(/[()]/g, '')
103
+ .replace(/[^a-z0-9\s-]/g, '')
104
+ .replace(/[\s-]+/g, '-')
105
+ .replace(/^-+|-+$/g, '');
106
+ }
107
+ global.BUILDSHIP_FIRESTORE_V7_CACHE = global.BUILDSHIP_FIRESTORE_V7_CACHE || {};
108
+ const DEFAULT_BRANCH = 'migratedprod';
109
+ function getFirestore(systemEnvName) {
110
+ const firebaseDb = (systemEnvName === DEFAULT_BRANCH ? '(default)' : systemEnvName);
111
+ if (!global.BUILDSHIP_FIRESTORE_V7_CACHE[systemEnvName]) {
112
+ let firestore;
113
+ if (global.BUILDSHIP_FIRESTORE_V7_INSTANCE) {
114
+ firestore = global.BUILDSHIP_FIRESTORE_V7_INSTANCE;
115
+ if (firestore.databaseId !== firebaseDb) {
116
+ firestore = new global.BUILDSHIP_FIRESTORE_V7_INSTANCE.constructor({
117
+ projectId: process.env.GCLOUD_PROJECT,
118
+ databaseId: firebaseDb,
119
+ });
120
+ }
121
+ }
122
+ else {
123
+ firestore = new firestore_1.Firestore({
124
+ projectId: process.env.GCLOUD_PROJECT,
125
+ databaseId: firebaseDb,
126
+ });
127
+ }
128
+ global.BUILDSHIP_FIRESTORE_V7_CACHE[systemEnvName] = firestore;
129
+ }
130
+ return global.BUILDSHIP_FIRESTORE_V7_CACHE[systemEnvName];
131
+ }
132
+ function createHandlerDecorator(decoratorFactory) {
133
+ return decoratorFactory;
134
+ }
135
+ async function getSecret(runtime, name, accessToken) {
136
+ if (name.startsWith('process.secret.')) {
137
+ name = name.slice('process.secret.'.length);
138
+ }
139
+ try {
140
+ const projectId = process.env.GCLOUD_PROJECT;
141
+ if (!projectId) {
142
+ throw new Error('GCLOUD_PROJECT env is not set');
143
+ }
144
+ const url = `https://secretmanager.googleapis.com/v1/projects/${projectId}/secrets/${runtime.systemEnvName}---${name}/versions/latest:access`;
145
+ const res = await fetch(url, {
146
+ headers: { Authorization: `Bearer ${accessToken}` }
147
+ });
148
+ if (!res.ok) {
149
+ const text = await res.text();
150
+ throw new Error(`secret access http ${res.status}: ${text}`);
151
+ }
152
+ const json = await res.json();
153
+ const dataB64 = json?.payload?.data || '';
154
+ if (!dataB64)
155
+ return '';
156
+ const payload = Buffer.from(dataB64, 'base64').toString('utf-8');
157
+ return payload;
158
+ }
159
+ catch (err) {
160
+ throw new Error(`Failed to get secret ${name}. Error: ${err.message}`);
161
+ }
162
+ }
163
+ const getAccessToken = async () => {
164
+ const metadataUrl = 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token';
165
+ try {
166
+ const res = await fetch(metadataUrl, {
167
+ headers: { 'Metadata-Flavor': 'Google' }
168
+ });
169
+ if (!res.ok) {
170
+ throw new Error(`metadata token http ${res.status}`);
171
+ }
172
+ const json = await res.json();
173
+ if (!json.access_token) {
174
+ throw new Error('missing access_token in metadata response');
175
+ }
176
+ return json.access_token;
177
+ }
178
+ catch (err) {
179
+ throw new Error(`Failed to obtain access token. Error: ${err.message}`);
180
+ }
181
+ };
182
+ exports.getAccessToken = getAccessToken;
183
+ const getIdentityToken = async (expectedAudience) => {
184
+ const metadataUrl = 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?' + new URLSearchParams({
185
+ audience: expectedAudience,
186
+ format: 'full',
187
+ }).toString();
188
+ try {
189
+ const res = await fetch(metadataUrl, {
190
+ headers: { 'Metadata-Flavor': 'Google' }
191
+ });
192
+ if (!res.ok) {
193
+ throw new Error(`metadata token http ${res.status}`);
194
+ }
195
+ const accessToken = await res.text();
196
+ if (!accessToken) {
197
+ throw new Error('missing access_token in metadata response');
198
+ }
199
+ return accessToken;
200
+ }
201
+ catch (err) {
202
+ throw new Error(`Failed to obtain identity token. Error: ${err.message}`);
203
+ }
204
+ };
205
+ exports.getIdentityToken = getIdentityToken;
206
+ function splitTimeToArr(date = new Date()) {
207
+ return [date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds()];
208
+ }
209
+ function minutesAgo(minutes) {
210
+ return new Date(Date.now() - minutes * 60 * 1000).toISOString();
211
+ }
212
+ function setRetryAfterVariable(value, options) {
213
+ let v = null;
214
+ if (value instanceof Response) {
215
+ v = value.headers.get('retry-after') || null;
216
+ }
217
+ else if (typeof v === 'object') {
218
+ if (value instanceof Headers) {
219
+ v = value.get('retry-after') || null;
220
+ }
221
+ else {
222
+ v = value['retry-after'] || null;
223
+ }
224
+ }
225
+ else if (typeof v !== 'string') {
226
+ v = null;
227
+ }
228
+ options.root.state['_$hsRetryAfter_'] = v;
229
+ return v;
230
+ }
231
+ global.functionsCache = global.functionsCache || {};
232
+ exports.FUNCTION_EXPR_ERROR = Symbol('function');
233
+ function createFunction(expression) {
234
+ if (!global.functionsCache[expression]) {
235
+ global.functionsCache[expression] = new Function('symbol', 'payload', 'try { return ' + expression + ' } catch (err) { return symbol; }');
236
+ }
237
+ return (payload) => global.functionsCache[expression](exports.FUNCTION_EXPR_ERROR, payload);
238
+ }
239
+ function onResponse(config, options) {
240
+ const flags = options.root[options.triggerId || options.trigger?.id].flags;
241
+ const numberOfInputMessages = options.root[options.triggerId || options.trigger?.id].body.length;
242
+ const outputBody = config.outputs.body;
243
+ const outputStatus = config.outputs.status;
244
+ let responsePayload;
245
+ let headersToSet = {};
246
+ if (outputBody.headersToSet && outputBody.body) {
247
+ responsePayload = outputBody.body;
248
+ headersToSet = outputBody.headersToSet;
249
+ }
250
+ else {
251
+ responsePayload = outputBody;
252
+ }
253
+ if (options.root?.state?.['_$hsRetryAfter_'] && !Object.keys(headersToSet).some(x => x.toLocaleLowerCase() === 'retry-after')) {
254
+ let retryAfter = options.root.state['_$hsRetryAfter_'];
255
+ if (retryAfter) {
256
+ if (/^\d+$/.test(retryAfter ?? '')) {
257
+ retryAfter = new Date(Date.now() + parseInt(retryAfter) * 1000).toString();
258
+ }
259
+ }
260
+ headersToSet['retry-after'] = retryAfter;
261
+ }
262
+ if (Array.isArray(responsePayload) && responsePayload.length === numberOfInputMessages) {
263
+ return {
264
+ status: (responsePayload.every(x => x instanceof Error) ? 500 : (outputStatus ? outputStatus : 200)),
265
+ value: responsePayload.map(x => {
266
+ if (x.status && x.body) {
267
+ return x;
268
+ }
269
+ return {
270
+ status: x instanceof Error ? (headersToSet['retry-after'] ? 429 : 500) : 200,
271
+ body: x instanceof Error ? x.message : (flags.includes('product-data') ? x : '<Redacted>. No product-data permissions>')
272
+ };
273
+ })
274
+ };
275
+ }
276
+ if (headersToSet) {
277
+ for (const [key, value] of Object.entries(headersToSet)) {
278
+ options.request.headers[key] = value;
279
+ }
280
+ }
281
+ return {
282
+ status: headersToSet['retry-after'] ? 429 : (outputStatus ? outputStatus : (responsePayload instanceof Error ? 500 : 200)),
283
+ value: responsePayload,
284
+ cacheMaxAge: 0,
285
+ };
286
+ }
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = validate;
7
+ const ajv_1 = __importDefault(require("ajv"));
8
+ const ajv_formats_1 = __importDefault(require("ajv-formats"));
9
+ function validate(payload, schema, options) {
10
+ const ajv = new ajv_1.default({
11
+ allErrors: true,
12
+ coerceTypes: false,
13
+ verbose: false,
14
+ strictSchema: false,
15
+ logger: {
16
+ log: options.log.log,
17
+ warn: options.log.log,
18
+ error: options.log.error,
19
+ },
20
+ });
21
+ (0, ajv_formats_1.default)(ajv);
22
+ const validate = ajv.compile(schema);
23
+ if (!validate(payload)) {
24
+ const errors = validate.errors?.map(error => `${error.instancePath} ${error.message}: ${JSON.stringify({
25
+ keyword: error.keyword,
26
+ instancePath: error.instancePath,
27
+ schemaPath: error.instancePath,
28
+ params: error.params,
29
+ propertyName: error.propertyName,
30
+ })}`) ||
31
+ [];
32
+ options.log.error(`Payload validation failed for object type '${schema.title || schema.$id}' because it did not match the expected schema.` +
33
+ errors.join('\n'));
34
+ throw new Error(`Payload validation failed for object type '${schema.title || schema.$id}' because it did not match the expected schema` +
35
+ errors.join('\n'));
36
+ }
37
+ else {
38
+ return payload;
39
+ }
40
+ }
package/dist/package.json CHANGED
@@ -10,6 +10,7 @@
10
10
  "ajv-formats": "^3.0.1",
11
11
  "co-body": "^6.2.0",
12
12
  "jose": "^6.0.11",
13
+ "lodash.chunk": "^4.2.0",
13
14
  "lodash.clonedeep": "^4.5.0",
14
15
  "lodash.isequal": "^4.5.0",
15
16
  "lodash.omit": "^4.5.0",
@@ -17,13 +18,15 @@
17
18
  "mime-types": "^3.0.1",
18
19
  "p-limit": "^7.1.1",
19
20
  "rate-limiter-flexible": "^7.2.0",
20
- "uuid": "^11.1.0"
21
+ "uuid": "^11.1.0",
22
+ "redis": "^5.6.0",
23
+ "@google-cloud/firestore": "^7.11.1"
21
24
  },
22
25
  "files": [
23
26
  "dist"
24
27
  ],
25
- "main": "dist/index.js",
26
- "types": "dist/index.d.ts",
28
+ "main": "dist/cjs/index.js",
29
+ "types": "dist/types/index.d.ts",
27
30
  "publishConfig": {
28
31
  "access": "public"
29
32
  }
@@ -0,0 +1,34 @@
1
+ declare const schema: {
2
+ readonly $schema: "http://json-schema.org/draft-07/schema#";
3
+ readonly title: "Asset";
4
+ readonly type: "object";
5
+ readonly additionalProperties: false;
6
+ readonly properties: {
7
+ readonly source_url: {
8
+ readonly type: "string";
9
+ };
10
+ readonly last_modified_at: {
11
+ readonly type: "string";
12
+ readonly format: "date-time";
13
+ };
14
+ readonly width: {
15
+ readonly type: "integer";
16
+ readonly minimum: 0;
17
+ };
18
+ readonly height: {
19
+ readonly type: "integer";
20
+ readonly minimum: 0;
21
+ };
22
+ readonly content_type: {
23
+ readonly type: "string";
24
+ readonly pattern: "^[a-z0-9-/]+$";
25
+ };
26
+ readonly file_name: {
27
+ readonly type: "string";
28
+ readonly pattern: "^[a-z0-9-.]+$";
29
+ };
30
+ };
31
+ readonly required: readonly ["source_url", "content_type", "last_modified_at"];
32
+ readonly $id: "https://shushed.example.com/asset.json";
33
+ };
34
+ export default schema;
@@ -0,0 +1,58 @@
1
+ declare const schema: {
2
+ readonly $schema: "http://json-schema.org/draft-07/schema#";
3
+ readonly title: "Category";
4
+ readonly additionalProperties: false;
5
+ readonly type: "object";
6
+ readonly properties: {
7
+ readonly centra_id: {
8
+ readonly type: "string";
9
+ };
10
+ readonly category_code: {
11
+ readonly type: "string";
12
+ };
13
+ readonly parent_category_code: {
14
+ readonly type: "string";
15
+ };
16
+ readonly parent_centra_id: {
17
+ readonly type: "string";
18
+ };
19
+ readonly categorisation_rules: {
20
+ readonly type: "array";
21
+ readonly items: {
22
+ readonly type: "string";
23
+ };
24
+ };
25
+ readonly translations: {
26
+ readonly type: "array";
27
+ readonly items: {
28
+ readonly type: "object";
29
+ readonly properties: {
30
+ readonly language_code: {
31
+ readonly type: "string";
32
+ };
33
+ readonly name: {
34
+ readonly type: "string";
35
+ };
36
+ };
37
+ };
38
+ };
39
+ readonly uri: {
40
+ readonly type: "string";
41
+ };
42
+ readonly name: {
43
+ readonly type: "string";
44
+ };
45
+ readonly status: {
46
+ readonly type: "string";
47
+ readonly enum: readonly ["ACTIVE", "INACTIVE", "DISABLED"];
48
+ };
49
+ };
50
+ readonly required: readonly ["name", "status", "translations"];
51
+ readonly anyOf: readonly [{
52
+ readonly required: readonly ["centra_id", "parent_centra_id"];
53
+ }, {
54
+ readonly required: readonly ["category_code", "parent_category_code"];
55
+ }];
56
+ readonly $id: "https://shushed.example.com/category.schema.json";
57
+ };
58
+ export default schema;
@@ -0,0 +1,8 @@
1
+ declare const schema: {
2
+ readonly $schema: "http://json-schema.org/draft-07/schema#";
3
+ readonly title: "Country";
4
+ readonly type: "string";
5
+ readonly enum: readonly ["AF", "AX", "AL", "DZ", "AS", "AD", "AO", "AI", "AQ", "AG", "AR", "AM", "AW", "AU", "AT", "AZ", "BS", "BH", "BD", "BB", "BY", "BE", "BZ", "BJ", "BM", "BT", "BO", "BQ", "BA", "BW", "BV", "BR", "IO", "BN", "BG", "BF", "BI", "CV", "KH", "CM", "CA", "KY", "CF", "TD", "CL", "CN", "CX", "CC", "CO", "KM", "CD", "CG", "CK", "CR", "CI", "HR", "CU", "CW", "CY", "CZ", "DK", "DJ", "DM", "DO", "EC", "EG", "SV", "GQ", "ER", "EE", "SZ", "ET", "FK", "FO", "FJ", "FI", "FR", "GF", "PF", "TF", "GA", "GM", "GE", "DE", "GH", "GI", "GR", "GL", "GD", "GP", "GU", "GT", "GG", "GN", "GW", "GY", "HT", "HM", "VA", "HN", "HK", "HU", "IS", "IN", "ID", "IR", "IQ", "IE", "IM", "IL", "IT", "JM", "JP", "JE", "JO", "KZ", "KE", "KI", "KP", "KR", "KW", "KG", "LA", "LV", "LB", "LS", "LR", "LY", "LI", "LT", "LU", "MO", "MG", "MW", "MY", "MV", "ML", "MT", "MH", "MQ", "MR", "MU", "YT", "MX", "FM", "MD", "MC", "MN", "ME", "MS", "MA", "MZ", "MM", "NA", "NR", "NP", "NL", "NC", "NZ", "NI", "NE", "NG", "NU", "NF", "MK", "MP", "NO", "OM", "PK", "PW", "PS", "PA", "PG", "PY", "PE", "PH", "PN", "PL", "PT", "PR", "QA", "RE", "RO", "RU", "RW", "BL", "SH", "KN", "LC", "MF", "PM", "VC", "WS", "SM", "ST", "SA", "SN", "RS", "SC", "SL", "SG", "SX", "SK", "SI", "SB", "SO", "ZA", "GS", "SS", "ES", "LK", "SD", "SR", "SJ", "SE", "CH", "SY", "TW", "TJ", "TZ", "TH", "TL", "TG", "TK", "TO", "TT", "TN", "TR", "TM", "TC", "TV", "UG", "UA", "AE", "GB", "UM", "US", "UY", "UZ", "VU", "VE", "VN", "VG", "VI", "WF", "EH", "YE", "ZM", "ZW"];
6
+ readonly $id: "https://shushed.example.com/country.schema.json";
7
+ };
8
+ export default schema;
@@ -0,0 +1,8 @@
1
+ declare const schema: {
2
+ readonly $schema: "http://json-schema.org/draft-07/schema#";
3
+ readonly title: "Currency";
4
+ readonly type: "string";
5
+ readonly enum: readonly ["AFN", "ALL", "DZD", "USD", "EUR", "AOA", "XCD", "ARS", "AMD", "AWG", "AUD", "AZN", "BSD", "BHD", "BDT", "BBD", "BYN", "BZD", "XOF", "BMD", "BTN", "INR", "BOB", "BOV", "BAM", "BWP", "NOK", "BRL", "BND", "BGN", "BIF", "CVE", "KHR", "XAF", "CAD", "KYD", "CLF", "CLP", "CNY", "COP", "COU", "KMF", "CDF", "NZD", "CRC", "CUC", "CUP", "ANG", "CZK", "DKK", "DJF", "DOP", "EGP", "SVC", "ERN", "ETB", "FKP", "FJD", "XPF", "GMD", "GEL", "GHS", "GIP", "GTQ", "GBP", "GNF", "GYD", "HTG", "HNL", "HKD", "HUF", "ISK", "IDR", "XDR", "IRR", "IQD", "ILS", "JMD", "JPY", "JOD", "KZT", "KES", "KPW", "KRW", "KWD", "KGS", "LAK", "LBP", "LSL", "ZAR", "LRD", "LYD", "CHF", "MOP", "MGA", "MWK", "MYR", "MVR", "MRU", "MUR", "XUA", "MXN", "MXV", "MDL", "MNT", "MAD", "MZN", "MMK", "NAD", "NPR", "NIO", "NGN", "OMR", "PKR", "PAB", "PGK", "PYG", "PEN", "PHP", "PLN", "QAR", "MKD", "RON", "RUB", "RWF", "SHP", "WST", "STN", "SAR", "RSD", "SCR", "SLE", "SGD", "XSU", "SBD", "SOS", "SSP", "LKR", "SDG", "SRD", "SZL", "SEK", "CHE", "CHW", "SYP", "TWD", "TJS", "TZS", "THB", "TOP", "TTD", "TND", "TRY", "TMT", "UGX", "UAH", "AED", "USN", "UYI", "UYU", "UZS", "VUV", "VEF", "VED", "VND", "YER", "ZMW", "ZWL"];
6
+ readonly $id: "https://shushed.example.com/currency.schema.json";
7
+ };
8
+ export default schema;
@@ -0,0 +1,26 @@
1
+ declare const schema: {
2
+ readonly $schema: "http://json-schema.org/draft-07/schema#";
3
+ readonly title: "CustomerSegment";
4
+ readonly type: "object";
5
+ readonly additionalProperties: false;
6
+ readonly properties: {
7
+ readonly bc_id: {
8
+ readonly type: "string";
9
+ readonly maxLength: 20;
10
+ };
11
+ readonly email: {
12
+ readonly type: "string";
13
+ readonly format: "email";
14
+ readonly example: "alice.johnson@example.com";
15
+ };
16
+ readonly segments: {
17
+ readonly type: readonly ["array", "null"];
18
+ readonly items: {
19
+ readonly type: "string";
20
+ };
21
+ };
22
+ };
23
+ readonly required: readonly ["bc_id", "email", "segments"];
24
+ readonly $id: "https://shushed.example.com/order/customer-segment.schema.json";
25
+ };
26
+ export default schema;
@@ -0,0 +1,97 @@
1
+ declare const schema: {
2
+ readonly $schema: "http://json-schema.org/draft-07/schema#";
3
+ readonly title: "Development Colour";
4
+ readonly type: "object";
5
+ readonly additionalProperties: false;
6
+ readonly properties: {
7
+ readonly colour_id: {
8
+ readonly type: "string";
9
+ };
10
+ readonly name: {
11
+ readonly type: readonly ["string", "null"];
12
+ };
13
+ readonly rgb: {
14
+ readonly anyOf: readonly [{
15
+ readonly type: "null";
16
+ }, {
17
+ readonly type: "array";
18
+ readonly items: {
19
+ readonly type: "number";
20
+ };
21
+ }];
22
+ };
23
+ readonly cmyk: {
24
+ readonly anyOf: readonly [{
25
+ readonly type: "null";
26
+ }, {
27
+ readonly type: "array";
28
+ readonly items: {
29
+ readonly type: "number";
30
+ };
31
+ }];
32
+ };
33
+ readonly pantone: {
34
+ readonly anyOf: readonly [{
35
+ readonly type: "null";
36
+ }, {
37
+ readonly type: "object";
38
+ readonly properties: {
39
+ readonly name: {
40
+ readonly type: "string";
41
+ };
42
+ readonly system: {
43
+ readonly type: "string";
44
+ readonly pattern: "^[A-Z0-9-]+$";
45
+ };
46
+ readonly id: {
47
+ readonly type: "string";
48
+ readonly pattern: "^[A-Z0-9-]+$";
49
+ };
50
+ };
51
+ }];
52
+ };
53
+ readonly display_name: {
54
+ readonly type: readonly ["string", "null"];
55
+ readonly pattern: "^[ a-z-]+$";
56
+ };
57
+ readonly family_display_name: {
58
+ readonly type: readonly ["string", "null"];
59
+ readonly pattern: "^[ a-z]+$";
60
+ };
61
+ readonly source_asset: {
62
+ readonly $schema: "http://json-schema.org/draft-07/schema#";
63
+ readonly title: "Asset";
64
+ readonly type: "object";
65
+ readonly additionalProperties: false;
66
+ readonly properties: {
67
+ readonly source_url: {
68
+ readonly type: "string";
69
+ };
70
+ readonly last_modified_at: {
71
+ readonly type: "string";
72
+ readonly format: "date-time";
73
+ };
74
+ readonly width: {
75
+ readonly type: "integer";
76
+ readonly minimum: 0;
77
+ };
78
+ readonly height: {
79
+ readonly type: "integer";
80
+ readonly minimum: 0;
81
+ };
82
+ readonly content_type: {
83
+ readonly type: "string";
84
+ readonly pattern: "^[a-z0-9-/]+$";
85
+ };
86
+ readonly file_name: {
87
+ readonly type: "string";
88
+ readonly pattern: "^[a-z0-9-.]+$";
89
+ };
90
+ };
91
+ readonly required: readonly ["source_url", "content_type", "last_modified_at"];
92
+ };
93
+ };
94
+ readonly required: readonly ["colour_id"];
95
+ readonly $id: "https://shushed.example.com/development-colour.schema.json";
96
+ };
97
+ export default schema;
@@ -0,0 +1,16 @@
1
+ export { default as Asset } from './asset';
2
+ export { default as Category } from './category';
3
+ export { default as Country } from './country';
4
+ export { default as Currency } from './currency';
5
+ export { default as CustomerSegment } from './customer-segment';
6
+ export { default as DevelopmentColour } from './development-colour';
7
+ export { default as MarketingPreferences } from './marketing-preferences';
8
+ export { default as Money } from './money';
9
+ export { default as Price } from './price';
10
+ export { default as ProductCategory } from './product-category';
11
+ export { default as ProductDraft } from './product-draft';
12
+ export { default as Product } from './product';
13
+ export { default as Stock } from './stock';
14
+ export { default as Total } from './total';
15
+ export * as Messages from './messages';
16
+ export * as Order from './order';
@@ -0,0 +1,31 @@
1
+ declare const schema: {
2
+ readonly $schema: "http://json-schema.org/draft-07/schema#";
3
+ readonly title: "MarketingPref";
4
+ readonly type: "object";
5
+ readonly additionalProperties: false;
6
+ readonly properties: {
7
+ readonly email_consent: {
8
+ readonly type: "boolean";
9
+ };
10
+ readonly catalogue_consent: {
11
+ readonly type: "boolean";
12
+ };
13
+ readonly phone_consent: {
14
+ readonly type: "boolean";
15
+ };
16
+ readonly "3rdparty_consent": {
17
+ readonly type: "boolean";
18
+ };
19
+ readonly svc_customer_id: {
20
+ readonly type: "string";
21
+ };
22
+ readonly email: {
23
+ readonly type: readonly ["string", "null"];
24
+ readonly format: "email";
25
+ readonly example: "alice.johnson@example.com";
26
+ };
27
+ };
28
+ readonly required: readonly ["email_consent", "email", "phone_consent", "svc_customer_id"];
29
+ readonly $id: "https://shushed.example.com/order/marketing-preferences.schema.json";
30
+ };
31
+ export default schema;
@@ -0,0 +1,17 @@
1
+ declare const schema: {
2
+ readonly $schema: "http://json-schema.org/draft-07/schema#";
3
+ readonly title: "EANChange";
4
+ readonly additionalProperties: false;
5
+ readonly type: "object";
6
+ readonly required: readonly ["sku", "ean"];
7
+ readonly properties: {
8
+ readonly sku: {
9
+ readonly type: "string";
10
+ };
11
+ readonly ean: {
12
+ readonly type: "string";
13
+ };
14
+ };
15
+ readonly $id: "https://shushed.example.com/messages/ean-change.schema.json";
16
+ };
17
+ export default schema;