@shushed/helpers 0.0.200-v2-20251128093319 → 0.0.200

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/index.d.ts +34970 -0
  2. package/dist/index.js +113017 -0
  3. package/dist/package.json +3 -6
  4. package/package.json +4 -7
  5. package/dist/cjs/dist-dereferenced/asset.js +0 -4
  6. package/dist/cjs/dist-dereferenced/category.js +0 -4
  7. package/dist/cjs/dist-dereferenced/country.js +0 -4
  8. package/dist/cjs/dist-dereferenced/currency.js +0 -4
  9. package/dist/cjs/dist-dereferenced/customer-segment.js +0 -4
  10. package/dist/cjs/dist-dereferenced/development-colour.js +0 -4
  11. package/dist/cjs/dist-dereferenced/index.js +0 -69
  12. package/dist/cjs/dist-dereferenced/marketing-preferences.js +0 -4
  13. package/dist/cjs/dist-dereferenced/messages/ean-change.js +0 -4
  14. package/dist/cjs/dist-dereferenced/messages/index.js +0 -50
  15. package/dist/cjs/dist-dereferenced/messages/order/delivered.js +0 -4
  16. package/dist/cjs/dist-dereferenced/messages/order/index.js +0 -18
  17. package/dist/cjs/dist-dereferenced/messages/order/new.js +0 -4
  18. package/dist/cjs/dist-dereferenced/messages/order/processed.js +0 -4
  19. package/dist/cjs/dist-dereferenced/messages/order/return-initiated.js +0 -4
  20. package/dist/cjs/dist-dereferenced/messages/order/returned.js +0 -4
  21. package/dist/cjs/dist-dereferenced/messages/order/shipped.js +0 -4
  22. package/dist/cjs/dist-dereferenced/messages/price-change.js +0 -4
  23. package/dist/cjs/dist-dereferenced/messages/product-category.js +0 -4
  24. package/dist/cjs/dist-dereferenced/messages/product-draft.js +0 -4
  25. package/dist/cjs/dist-dereferenced/messages/product.js +0 -4
  26. package/dist/cjs/dist-dereferenced/money.js +0 -4
  27. package/dist/cjs/dist-dereferenced/order/address.js +0 -4
  28. package/dist/cjs/dist-dereferenced/order/customer.js +0 -4
  29. package/dist/cjs/dist-dereferenced/order/index.js +0 -51
  30. package/dist/cjs/dist-dereferenced/order/item.js +0 -4
  31. package/dist/cjs/dist-dereferenced/order/orderMain.js +0 -4
  32. package/dist/cjs/dist-dereferenced/order/payment.js +0 -4
  33. package/dist/cjs/dist-dereferenced/order/shipment/index.js +0 -45
  34. package/dist/cjs/dist-dereferenced/order/shipment/item/index.js +0 -11
  35. package/dist/cjs/dist-dereferenced/order/shipment/item/itemMain.js +0 -4
  36. package/dist/cjs/dist-dereferenced/order/shipment/item/returned.js +0 -4
  37. package/dist/cjs/dist-dereferenced/order/shipment/pos/index.js +0 -13
  38. package/dist/cjs/dist-dereferenced/order/shipment/pos/outbound.js +0 -4
  39. package/dist/cjs/dist-dereferenced/order/shipment/pos/posMain.js +0 -4
  40. package/dist/cjs/dist-dereferenced/order/shipment/pos/return.js +0 -4
  41. package/dist/cjs/dist-dereferenced/order/shipment/shipmentMain.js +0 -4
  42. package/dist/cjs/dist-dereferenced/order/shipment/shipped/index.js +0 -13
  43. package/dist/cjs/dist-dereferenced/order/shipment/shipped/outbound.js +0 -4
  44. package/dist/cjs/dist-dereferenced/order/shipment/shipped/return.js +0 -4
  45. package/dist/cjs/dist-dereferenced/order/shipment/shipped/shippedMain.js +0 -4
  46. package/dist/cjs/dist-dereferenced/price.js +0 -4
  47. package/dist/cjs/dist-dereferenced/product-category.js +0 -4
  48. package/dist/cjs/dist-dereferenced/product-draft.js +0 -4
  49. package/dist/cjs/dist-dereferenced/product.js +0 -4
  50. package/dist/cjs/dist-dereferenced/stock.js +0 -4
  51. package/dist/cjs/dist-dereferenced/total.js +0 -4
  52. package/dist/cjs/dist-types/asset.js +0 -2
  53. package/dist/cjs/dist-types/category.js +0 -2
  54. package/dist/cjs/dist-types/country.js +0 -2
  55. package/dist/cjs/dist-types/currency.js +0 -2
  56. package/dist/cjs/dist-types/customer-segment.js +0 -2
  57. package/dist/cjs/dist-types/development-colour.js +0 -2
  58. package/dist/cjs/dist-types/index.js +0 -38
  59. package/dist/cjs/dist-types/marketing-preferences.js +0 -2
  60. package/dist/cjs/dist-types/messages/ean-change.js +0 -2
  61. package/dist/cjs/dist-types/messages/index.js +0 -37
  62. package/dist/cjs/dist-types/messages/order/delivered.js +0 -2
  63. package/dist/cjs/dist-types/messages/order/index.js +0 -2
  64. package/dist/cjs/dist-types/messages/order/new.js +0 -2
  65. package/dist/cjs/dist-types/messages/order/processed.js +0 -2
  66. package/dist/cjs/dist-types/messages/order/return-initiated.js +0 -2
  67. package/dist/cjs/dist-types/messages/order/returned.js +0 -2
  68. package/dist/cjs/dist-types/messages/order/shipped.js +0 -2
  69. package/dist/cjs/dist-types/messages/price-change.js +0 -2
  70. package/dist/cjs/dist-types/messages/product-category.js +0 -2
  71. package/dist/cjs/dist-types/messages/product-draft.js +0 -2
  72. package/dist/cjs/dist-types/messages/product.js +0 -2
  73. package/dist/cjs/dist-types/money.js +0 -2
  74. package/dist/cjs/dist-types/order/address.js +0 -2
  75. package/dist/cjs/dist-types/order/customer.js +0 -2
  76. package/dist/cjs/dist-types/order/index.js +0 -37
  77. package/dist/cjs/dist-types/order/item.js +0 -2
  78. package/dist/cjs/dist-types/order/orderMain.js +0 -2
  79. package/dist/cjs/dist-types/order/payment.js +0 -2
  80. package/dist/cjs/dist-types/order/shipment/index.js +0 -39
  81. package/dist/cjs/dist-types/order/shipment/item/index.js +0 -2
  82. package/dist/cjs/dist-types/order/shipment/item/itemMain.js +0 -2
  83. package/dist/cjs/dist-types/order/shipment/item/returned.js +0 -2
  84. package/dist/cjs/dist-types/order/shipment/pos/index.js +0 -2
  85. package/dist/cjs/dist-types/order/shipment/pos/outbound.js +0 -2
  86. package/dist/cjs/dist-types/order/shipment/pos/posMain.js +0 -2
  87. package/dist/cjs/dist-types/order/shipment/pos/return.js +0 -2
  88. package/dist/cjs/dist-types/order/shipment/shipmentMain.js +0 -2
  89. package/dist/cjs/dist-types/order/shipment/shipped/index.js +0 -2
  90. package/dist/cjs/dist-types/order/shipment/shipped/outbound.js +0 -2
  91. package/dist/cjs/dist-types/order/shipment/shipped/return.js +0 -2
  92. package/dist/cjs/dist-types/order/shipment/shipped/shippedMain.js +0 -2
  93. package/dist/cjs/dist-types/price.js +0 -2
  94. package/dist/cjs/dist-types/product-category.js +0 -2
  95. package/dist/cjs/dist-types/product-draft.js +0 -2
  96. package/dist/cjs/dist-types/product.js +0 -2
  97. package/dist/cjs/dist-types/stock.js +0 -2
  98. package/dist/cjs/dist-types/total.js +0 -2
  99. package/dist/cjs/index.js +0 -39
  100. package/dist/cjs/src-public/airtable.js +0 -590
  101. package/dist/cjs/src-public/bigquery.js +0 -59
  102. package/dist/cjs/src-public/cloudtasks.js +0 -207
  103. package/dist/cjs/src-public/dato.js +0 -680
  104. package/dist/cjs/src-public/env.js +0 -897
  105. package/dist/cjs/src-public/getEventTime.js +0 -28
  106. package/dist/cjs/src-public/index.js +0 -50
  107. package/dist/cjs/src-public/ipValidation.js +0 -167
  108. package/dist/cjs/src-public/jwks.js +0 -108
  109. package/dist/cjs/src-public/pubsub.js +0 -423
  110. package/dist/cjs/src-public/rateLimit.js +0 -140
  111. package/dist/cjs/src-public/redisClient.js +0 -44
  112. package/dist/cjs/src-public/runtime.js +0 -141
  113. package/dist/cjs/src-public/sanitize.js +0 -25
  114. package/dist/cjs/src-public/scheduler.js +0 -247
  115. package/dist/cjs/src-public/secret.js +0 -16
  116. package/dist/cjs/src-public/setHeaders.js +0 -16
  117. package/dist/cjs/src-public/types.js +0 -2
  118. package/dist/cjs/src-public/utils.js +0 -454
  119. package/dist/cjs/src-public/validate.js +0 -40
  120. package/dist/types/dist-dereferenced/asset.d.ts +0 -51
  121. package/dist/types/dist-dereferenced/category.d.ts +0 -58
  122. package/dist/types/dist-dereferenced/country.d.ts +0 -8
  123. package/dist/types/dist-dereferenced/currency.d.ts +0 -8
  124. package/dist/types/dist-dereferenced/customer-segment.d.ts +0 -26
  125. package/dist/types/dist-dereferenced/development-colour.d.ts +0 -114
  126. package/dist/types/dist-dereferenced/index.d.ts +0 -16
  127. package/dist/types/dist-dereferenced/marketing-preferences.d.ts +0 -31
  128. package/dist/types/dist-dereferenced/messages/ean-change.d.ts +0 -17
  129. package/dist/types/dist-dereferenced/messages/index.d.ts +0 -6
  130. package/dist/types/dist-dereferenced/messages/order/delivered.d.ts +0 -3414
  131. package/dist/types/dist-dereferenced/messages/order/index.d.ts +0 -6
  132. package/dist/types/dist-dereferenced/messages/order/new.d.ts +0 -3414
  133. package/dist/types/dist-dereferenced/messages/order/processed.d.ts +0 -3408
  134. package/dist/types/dist-dereferenced/messages/order/return-initiated.d.ts +0 -3414
  135. package/dist/types/dist-dereferenced/messages/order/returned.d.ts +0 -3413
  136. package/dist/types/dist-dereferenced/messages/order/shipped.d.ts +0 -3412
  137. package/dist/types/dist-dereferenced/messages/price-change.d.ts +0 -67
  138. package/dist/types/dist-dereferenced/messages/product-category.d.ts +0 -33
  139. package/dist/types/dist-dereferenced/messages/product-draft.d.ts +0 -589
  140. package/dist/types/dist-dereferenced/messages/product.d.ts +0 -628
  141. package/dist/types/dist-dereferenced/money.d.ts +0 -41
  142. package/dist/types/dist-dereferenced/order/address.d.ts +0 -98
  143. package/dist/types/dist-dereferenced/order/customer.d.ts +0 -309
  144. package/dist/types/dist-dereferenced/order/index.d.ts +0 -3404
  145. package/dist/types/dist-dereferenced/order/item.d.ts +0 -336
  146. package/dist/types/dist-dereferenced/order/orderMain.d.ts +0 -3399
  147. package/dist/types/dist-dereferenced/order/payment.d.ts +0 -94
  148. package/dist/types/dist-dereferenced/order/shipment/index.d.ts +0 -253
  149. package/dist/types/dist-dereferenced/order/shipment/item/index.d.ts +0 -19
  150. package/dist/types/dist-dereferenced/order/shipment/item/itemMain.d.ts +0 -18
  151. package/dist/types/dist-dereferenced/order/shipment/item/returned.d.ts +0 -34
  152. package/dist/types/dist-dereferenced/order/shipment/pos/index.d.ts +0 -282
  153. package/dist/types/dist-dereferenced/order/shipment/pos/outbound.d.ts +0 -320
  154. package/dist/types/dist-dereferenced/order/shipment/pos/posMain.d.ts +0 -280
  155. package/dist/types/dist-dereferenced/order/shipment/pos/return.d.ts +0 -331
  156. package/dist/types/dist-dereferenced/order/shipment/shipmentMain.d.ts +0 -250
  157. package/dist/types/dist-dereferenced/order/shipment/shipped/index.d.ts +0 -288
  158. package/dist/types/dist-dereferenced/order/shipment/shipped/outbound.d.ts +0 -286
  159. package/dist/types/dist-dereferenced/order/shipment/shipped/return.d.ts +0 -287
  160. package/dist/types/dist-dereferenced/order/shipment/shipped/shippedMain.d.ts +0 -286
  161. package/dist/types/dist-dereferenced/price.d.ts +0 -58
  162. package/dist/types/dist-dereferenced/product-category.d.ts +0 -24
  163. package/dist/types/dist-dereferenced/product-draft.d.ts +0 -580
  164. package/dist/types/dist-dereferenced/product.d.ts +0 -619
  165. package/dist/types/dist-dereferenced/stock.d.ts +0 -74
  166. package/dist/types/dist-dereferenced/total.d.ts +0 -172
  167. package/dist/types/dist-types/asset.d.ts +0 -16
  168. package/dist/types/dist-types/category.d.ts +0 -20
  169. package/dist/types/dist-types/country.d.ts +0 -2
  170. package/dist/types/dist-types/currency.d.ts +0 -2
  171. package/dist/types/dist-types/customer-segment.d.ts +0 -6
  172. package/dist/types/dist-types/development-colour.d.ts +0 -31
  173. package/dist/types/dist-types/index.d.ts +0 -16
  174. package/dist/types/dist-types/marketing-preferences.d.ts +0 -9
  175. package/dist/types/dist-types/messages/ean-change.d.ts +0 -5
  176. package/dist/types/dist-types/messages/index.d.ts +0 -6
  177. package/dist/types/dist-types/messages/order/delivered.d.ts +0 -292
  178. package/dist/types/dist-types/messages/order/index.d.ts +0 -6
  179. package/dist/types/dist-types/messages/order/new.d.ts +0 -292
  180. package/dist/types/dist-types/messages/order/processed.d.ts +0 -292
  181. package/dist/types/dist-types/messages/order/return-initiated.d.ts +0 -292
  182. package/dist/types/dist-types/messages/order/returned.d.ts +0 -293
  183. package/dist/types/dist-types/messages/order/shipped.d.ts +0 -293
  184. package/dist/types/dist-types/messages/price-change.d.ts +0 -16
  185. package/dist/types/dist-types/messages/product-category.d.ts +0 -7
  186. package/dist/types/dist-types/messages/product-draft.d.ts +0 -136
  187. package/dist/types/dist-types/messages/product.d.ts +0 -144
  188. package/dist/types/dist-types/money.d.ts +0 -11
  189. package/dist/types/dist-types/order/address.d.ts +0 -27
  190. package/dist/types/dist-types/order/customer.d.ts +0 -81
  191. package/dist/types/dist-types/order/index.d.ts +0 -8
  192. package/dist/types/dist-types/order/item.d.ts +0 -85
  193. package/dist/types/dist-types/order/orderMain.d.ts +0 -289
  194. package/dist/types/dist-types/order/payment.d.ts +0 -26
  195. package/dist/types/dist-types/order/shipment/index.d.ts +0 -6
  196. package/dist/types/dist-types/order/shipment/item/index.d.ts +0 -4
  197. package/dist/types/dist-types/order/shipment/item/itemMain.d.ts +0 -6
  198. package/dist/types/dist-types/order/shipment/item/returned.d.ts +0 -11
  199. package/dist/types/dist-types/order/shipment/pos/index.d.ts +0 -5
  200. package/dist/types/dist-types/order/shipment/pos/outbound.d.ts +0 -76
  201. package/dist/types/dist-types/order/shipment/pos/posMain.d.ts +0 -71
  202. package/dist/types/dist-types/order/shipment/pos/return.d.ts +0 -75
  203. package/dist/types/dist-types/order/shipment/shipmentMain.d.ts +0 -62
  204. package/dist/types/dist-types/order/shipment/shipped/index.d.ts +0 -5
  205. package/dist/types/dist-types/order/shipment/shipped/outbound.d.ts +0 -68
  206. package/dist/types/dist-types/order/shipment/shipped/return.d.ts +0 -68
  207. package/dist/types/dist-types/order/shipment/shipped/shippedMain.d.ts +0 -69
  208. package/dist/types/dist-types/price.d.ts +0 -15
  209. package/dist/types/dist-types/product-category.d.ts +0 -6
  210. package/dist/types/dist-types/product-draft.d.ts +0 -135
  211. package/dist/types/dist-types/product.d.ts +0 -143
  212. package/dist/types/dist-types/stock.d.ts +0 -19
  213. package/dist/types/dist-types/total.d.ts +0 -44
  214. package/dist/types/index.d.ts +0 -3
  215. package/dist/types/src-public/airtable.d.ts +0 -220
  216. package/dist/types/src-public/bigquery.d.ts +0 -17
  217. package/dist/types/src-public/cloudtasks.d.ts +0 -74
  218. package/dist/types/src-public/dato.d.ts +0 -95
  219. package/dist/types/src-public/env.d.ts +0 -144
  220. package/dist/types/src-public/getEventTime.d.ts +0 -1
  221. package/dist/types/src-public/index.d.ts +0 -16
  222. package/dist/types/src-public/ipValidation.d.ts +0 -15
  223. package/dist/types/src-public/jwks.d.ts +0 -15
  224. package/dist/types/src-public/pubsub.d.ts +0 -95
  225. package/dist/types/src-public/rateLimit.d.ts +0 -21
  226. package/dist/types/src-public/redisClient.d.ts +0 -6
  227. package/dist/types/src-public/runtime.d.ts +0 -57
  228. package/dist/types/src-public/sanitize.d.ts +0 -4
  229. package/dist/types/src-public/scheduler.d.ts +0 -71
  230. package/dist/types/src-public/secret.d.ts +0 -6
  231. package/dist/types/src-public/setHeaders.d.ts +0 -13
  232. package/dist/types/src-public/types.d.ts +0 -264
  233. package/dist/types/src-public/utils.d.ts +0 -101
  234. package/dist/types/src-public/validate.d.ts +0 -9
@@ -1,680 +0,0 @@
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
- const fs_1 = __importDefault(require("fs"));
7
- const path_1 = __importDefault(require("path"));
8
- const mime_types_1 = require("mime-types");
9
- const runtime_1 = __importDefault(require("./runtime"));
10
- const utils_1 = require("./utils");
11
- class DatoHelper extends runtime_1.default {
12
- apiToken;
13
- baseUrl;
14
- environment;
15
- root;
16
- constructor(opts, datoOpts) {
17
- super(opts);
18
- this.apiToken = datoOpts.apiToken;
19
- this.baseUrl = datoOpts.baseUrl || 'https://site-api.datocms.com';
20
- this.environment = datoOpts.environment || 'main';
21
- this.root = datoOpts.root;
22
- }
23
- handle429(response) {
24
- if (response.status === 429 && this.root) {
25
- (0, utils_1.setRetryAfterVariable)(response, { root: this.root });
26
- }
27
- }
28
- async requestUploadParameters(filename) {
29
- const response = await fetch(`${this.baseUrl}/upload-requests`, {
30
- method: 'POST',
31
- headers: {
32
- 'X-Api-Version': '3',
33
- 'X-Environment': this.environment,
34
- 'Authorization': `Bearer ${this.apiToken}`,
35
- 'Content-Type': "application/vnd.api+json",
36
- 'Accept': 'application/json',
37
- },
38
- body: JSON.stringify({
39
- data: {
40
- type: 'upload_request',
41
- attributes: {
42
- filename: filename,
43
- },
44
- },
45
- }),
46
- });
47
- this.handle429(response);
48
- if (!response.ok) {
49
- const errorText = await response.text();
50
- this.logging.error(`Failed to request upload parameters: ${response.statusText} - ${errorText}`);
51
- throw new Error(`Failed to request upload parameters: ${response.statusText} - ${errorText}`);
52
- }
53
- return await response.json();
54
- }
55
- async uploadToStorageBucket(opts, uploadData, fileStream) {
56
- let blob;
57
- if (fileStream instanceof ReadableStream) {
58
- const response = new Response(fileStream);
59
- blob = await response.blob();
60
- }
61
- else {
62
- const chunks = [];
63
- for await (const chunk of fileStream) {
64
- chunks.push(chunk);
65
- }
66
- const buffer = Buffer.concat(chunks);
67
- blob = new Blob([buffer]);
68
- }
69
- const response = await fetch(uploadData.attributes.url, {
70
- method: 'PUT',
71
- headers: {
72
- 'Content-Type': opts.contentType,
73
- },
74
- body: blob,
75
- });
76
- if (!response.ok) {
77
- const errorText = await response.text();
78
- this.logging.error(`Failed to upload to storage bucket: ${response.statusText} - ${errorText}`);
79
- throw new Error(`Failed to upload to storage bucket: ${response.statusText} - ${errorText}`);
80
- }
81
- return response;
82
- }
83
- async createAssetFromUpload(uploadId, opts, uploadCollectionId) {
84
- const normalizedTags = Array.isArray(opts.tags) && opts.tags.length > 0
85
- ? opts.tags
86
- : ["integrations"];
87
- const safeTitle = opts.title && opts.title.trim().length > 0 ? opts.title : "untitled";
88
- const safeAlt = opts.alt && opts.alt.trim().length > 0 ? opts.alt : safeTitle;
89
- const body = {
90
- data: {
91
- type: 'upload',
92
- attributes: {
93
- path: uploadId,
94
- author: opts.author,
95
- copyright: opts.copyright,
96
- notes: opts.notes || null,
97
- title: safeTitle,
98
- alt: safeAlt,
99
- default_field_metadata: {
100
- "en-GB": {
101
- title: safeTitle,
102
- alt: safeAlt,
103
- custom_data: {
104
- source: normalizedTags[0] || "uploaded-by-integrations",
105
- tags: normalizedTags,
106
- }
107
- },
108
- en: {
109
- title: safeTitle,
110
- alt: safeAlt,
111
- custom_data: {
112
- source: normalizedTags[0] || "uploaded-by-integrations",
113
- tags: normalizedTags,
114
- }
115
- },
116
- "en-US": {
117
- title: safeTitle,
118
- alt: safeAlt,
119
- custom_data: {
120
- source: normalizedTags[0] || "uploaded-by-integrations",
121
- tags: normalizedTags,
122
- }
123
- }
124
- },
125
- tags: normalizedTags || [],
126
- },
127
- },
128
- };
129
- if (uploadCollectionId) {
130
- body.data.relationships = {
131
- upload_collection: {
132
- data: {
133
- type: 'upload_collection',
134
- id: uploadCollectionId,
135
- },
136
- },
137
- };
138
- }
139
- const response = await fetch(`${this.baseUrl}/uploads`, {
140
- method: 'POST',
141
- headers: {
142
- 'Authorization': `Bearer ${this.apiToken}`,
143
- 'Accept': 'application/json',
144
- 'X-Api-Version': '3',
145
- 'X-Environment': this.environment,
146
- 'Content-Type': 'application/vnd.api+json',
147
- },
148
- body: JSON.stringify(body),
149
- });
150
- this.handle429(response);
151
- if (!response.ok) {
152
- const errorText = await response.text();
153
- this.logging.error(`Failed to create asset from upload: ${response.statusText} - ${errorText}`);
154
- throw new Error(`Failed to create asset from upload: ${response.statusText} - ${errorText}`);
155
- }
156
- return await response.json();
157
- }
158
- async checkJobResult(jobId) {
159
- const response = await fetch(`${this.baseUrl}/job-results/${jobId}`, {
160
- method: 'GET',
161
- headers: {
162
- 'Authorization': `Bearer ${this.apiToken}`,
163
- 'Accept': 'application/json',
164
- 'X-Api-Version': '3',
165
- 'X-Environment': this.environment
166
- },
167
- });
168
- this.handle429(response);
169
- if (!response.ok) {
170
- if (response.status === 404) {
171
- return null;
172
- }
173
- const errorText = await response.text();
174
- this.logging.error(`Failed to check job result: ${response.statusText} - ${errorText}`);
175
- throw new Error(`Failed to check job result: ${response.statusText} - ${errorText}`);
176
- }
177
- return await response.json();
178
- }
179
- async waitForJobCompletion(jobId, maxAttempts = 30) {
180
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
181
- const jobResult = await this.checkJobResult(jobId);
182
- if (jobResult?.data.attributes.status >= 200 && jobResult?.data.attributes.status < 300) {
183
- return jobResult.data.attributes.payload;
184
- }
185
- if (jobResult?.data.attributes.status) {
186
- const errorMsg = `Job failed: ${JSON.stringify(jobResult.data)}`;
187
- this.logging.error(errorMsg);
188
- throw new Error(errorMsg);
189
- }
190
- await new Promise(resolve => setTimeout(resolve, 1000));
191
- }
192
- const timeoutMsg = 'Job completion timeout';
193
- this.logging.error(timeoutMsg);
194
- throw new Error(timeoutMsg);
195
- }
196
- updateUpload = async (options) => {
197
- try {
198
- this.logging.log(`Starting update upload - ${JSON.stringify(options)}`);
199
- if (!options.id)
200
- throw new Error("updateUpload requires 'id' in options");
201
- const safeTitle = options.title && options.title.trim().length > 0
202
- ? options.title.trim()
203
- : options.filename?.trim().split(".")[0] || "untitled";
204
- const safeAlt = options.alt && options.alt.trim().length > 0
205
- ? options.alt.trim()
206
- : safeTitle;
207
- const normalizedTags = Array.isArray(options.tags) && options.tags.length > 0
208
- ? options.tags
209
- : ["integrations"];
210
- const body = {
211
- data: {
212
- type: "upload",
213
- id: options.id,
214
- attributes: {
215
- author: options.author,
216
- copyright: options.copyright,
217
- tags: normalizedTags,
218
- notes: options.notes || null,
219
- default_field_metadata: {
220
- "en-GB": {
221
- title: safeTitle,
222
- alt: safeAlt,
223
- custom_data: {
224
- source: normalizedTags[0] || "uploaded-by-integrations",
225
- tags: normalizedTags,
226
- },
227
- },
228
- en: {
229
- title: safeTitle,
230
- alt: safeAlt,
231
- custom_data: {
232
- source: normalizedTags[0] || "uploaded-by-integrations",
233
- tags: normalizedTags,
234
- },
235
- },
236
- "en-US": {
237
- title: safeTitle,
238
- alt: safeAlt,
239
- custom_data: {
240
- source: normalizedTags[0] || "uploaded-by-integrations",
241
- tags: normalizedTags,
242
- },
243
- },
244
- },
245
- },
246
- },
247
- };
248
- if (options.uploadCollectionId) {
249
- body.data.relationships = {
250
- upload_collection: {
251
- data: {
252
- type: "upload_collection",
253
- id: options.uploadCollectionId,
254
- },
255
- },
256
- };
257
- }
258
- const response = await fetch(`${this.baseUrl}/uploads/${options.id}`, {
259
- method: "PATCH",
260
- headers: {
261
- Authorization: `Bearer ${this.apiToken}`,
262
- "X-Api-Version": "3",
263
- "X-Environment": this.environment,
264
- "Content-Type": "application/vnd.api+json",
265
- Accept: "application/json",
266
- },
267
- body: JSON.stringify(body),
268
- });
269
- this.handle429(response);
270
- if (!response.ok) {
271
- const errorText = await response.text();
272
- this.logging.error(`Failed to update upload: ${response.statusText} - ${errorText}`);
273
- throw new Error(`Failed to update upload: ${response.statusText} - ${errorText}`);
274
- }
275
- const updated = await response.json();
276
- if (Array.isArray(updated.data) && updated.data[0]?.type === "api_error") {
277
- const errorCode = updated.data[0].attributes?.code || "UNKNOWN_ERROR";
278
- const errorMsg = `DatoCMS API error: ${errorCode}`;
279
- this.logging.error(errorMsg);
280
- throw new Error(errorMsg);
281
- }
282
- if (updated.data?.type === "job") {
283
- this.logging.log(`Waiting for job completion: ${updated.data.id}`);
284
- const jobPayload = await this.waitForJobCompletion(updated.data.id);
285
- const assetId = jobPayload?.data?.id;
286
- const assetUrl = jobPayload?.data?.attributes?.url;
287
- if (!assetId || !assetUrl) {
288
- throw new Error(`Job completed but payload missing expected fields: ${JSON.stringify(jobPayload)}`);
289
- }
290
- this.logging.log(`Job completed for upload: ${assetId}`);
291
- return { success: true, assetId, upload: assetUrl };
292
- }
293
- if (updated.data?.type === "upload") {
294
- const { id, attributes } = updated.data;
295
- this.logging.log(`Upload updated successfully: ${id}`);
296
- return { success: true, assetId: id, upload: attributes.url };
297
- }
298
- const errMsg = `Unexpected update response: ${JSON.stringify(updated)}`;
299
- this.logging.error(errMsg);
300
- throw new Error(errMsg);
301
- }
302
- catch (err) {
303
- const msg = err?.message ?? JSON.stringify(err);
304
- this.logging.error(`[updateUpload] failed: ${msg}`);
305
- throw new Error(msg);
306
- }
307
- };
308
- async uploadFromUrl(options) {
309
- const { url, filename, uploadCollectionId, skipCreationIfAlreadyExists } = options;
310
- this.logging.log(`Starting upload from URL: ${url}`);
311
- const fileResponse = await fetch(url);
312
- if (!fileResponse.ok) {
313
- const errorMsg = `Failed to fetch file from URL: ${fileResponse.statusText}`;
314
- this.logging.error(errorMsg);
315
- throw new Error(errorMsg);
316
- }
317
- let finalFilename = filename || path_1.default.basename(new URL(url).pathname) ||
318
- `bs-${this.triggerId}-${Date.now()}`;
319
- if (filename && !path_1.default.extname(finalFilename)) {
320
- const urlObj = new URL(url);
321
- const pathname = urlObj.pathname;
322
- if (pathname.includes(".")) {
323
- const urlExtension = path_1.default.extname(pathname);
324
- if (urlExtension) {
325
- finalFilename += urlExtension;
326
- }
327
- }
328
- if (!path_1.default.extname(finalFilename) && fileResponse.headers.has('content-type')) {
329
- const ext = (0, mime_types_1.extension)(fileResponse.headers.get('content-type'));
330
- if (typeof ext === "string" && ext.length > 0) {
331
- finalFilename += `.${ext}`;
332
- }
333
- }
334
- }
335
- else if (!filename) {
336
- if (!path_1.default.extname(finalFilename) && fileResponse.headers.has('content-type')) {
337
- const ext = (0, mime_types_1.extension)(fileResponse.headers.get('content-type'));
338
- if (typeof ext === "string" && ext.length > 0) {
339
- finalFilename += `.${ext}`;
340
- }
341
- }
342
- }
343
- if (skipCreationIfAlreadyExists) {
344
- const existing = await this.findUploadByFilename(finalFilename);
345
- if (existing) {
346
- this.logging.log(`Skipping upload: existing asset found for "${finalFilename}"`);
347
- return {
348
- success: true,
349
- assetId: existing.id,
350
- upload: existing.attributes.url,
351
- skipped: true,
352
- };
353
- }
354
- }
355
- const uploadRequest = await this.requestUploadParameters(finalFilename);
356
- const uploadId = uploadRequest.data.id;
357
- if (!fileResponse.body) {
358
- throw new Error('Response body is null');
359
- }
360
- const contentType = fileResponse.headers.get('content-type') || (0, mime_types_1.lookup)(finalFilename) || 'application/octet-stream';
361
- await this.uploadToStorageBucket({ contentType }, uploadRequest.data, fileResponse.body);
362
- const assetJob = await this.createAssetFromUpload(uploadId, options, uploadCollectionId);
363
- const jobId = assetJob.data.id;
364
- const assetPayload = await this.waitForJobCompletion(jobId);
365
- this.logging.log(`Upload completed successfully: ${assetPayload.data.attributes.url}`);
366
- return {
367
- success: true,
368
- upload: assetPayload.data.attributes.url,
369
- assetId: assetPayload.data.id,
370
- skipped: false,
371
- };
372
- }
373
- async uploadFromFile(options) {
374
- const { filePath, filename, uploadCollectionId } = options;
375
- if (!fs_1.default.existsSync(filePath)) {
376
- const errorMsg = `File not found: ${filePath}`;
377
- this.logging.error(errorMsg);
378
- throw new Error(errorMsg);
379
- }
380
- this.logging.log(`Starting upload from file: ${filePath}`);
381
- const finalFilename = filename || path_1.default.basename(filePath);
382
- const uploadRequest = await this.requestUploadParameters(finalFilename);
383
- const uploadId = uploadRequest.data.id;
384
- const fileStream = fs_1.default.createReadStream(filePath);
385
- const contentType = (0, mime_types_1.lookup)(filePath) || 'application/octet-stream';
386
- await this.uploadToStorageBucket({ contentType }, uploadRequest.data, fileStream);
387
- const assetJob = await this.createAssetFromUpload(uploadId, options, uploadCollectionId);
388
- const jobId = assetJob.data.id;
389
- const assetPayload = await this.waitForJobCompletion(jobId);
390
- this.logging.log(`Upload completed successfully: ${assetPayload.data.attributes.url}`);
391
- return {
392
- success: true,
393
- upload: assetPayload.data.attributes.url,
394
- assetId: assetPayload.data.id,
395
- };
396
- }
397
- async getUploadCollections() {
398
- const response = await fetch(`${this.baseUrl}/upload-collections`, {
399
- method: 'GET',
400
- headers: {
401
- 'X-Api-Version': '3',
402
- 'X-Environment': this.environment,
403
- 'Authorization': `Bearer ${this.apiToken}`,
404
- 'Accept': 'application/json',
405
- },
406
- });
407
- this.handle429(response);
408
- if (!response.ok) {
409
- const errorText = await response.text();
410
- this.logging.error(`Failed to fetch upload collections: ${response.statusText} - ${errorText}`);
411
- throw new Error(`Failed to fetch upload collections: ${response.statusText} - ${errorText}`);
412
- }
413
- return await response.json();
414
- }
415
- async findUploadCollectionByLabel(label) {
416
- const collections = await this.getUploadCollections();
417
- return collections.data?.find((collection) => collection.attributes.label === label) || null;
418
- }
419
- static buildUrl(asset, opts) {
420
- const src = (asset ?? '').trim();
421
- const hasAnyNewOption = typeof opts.width === 'number' ||
422
- typeof opts.height === 'number' ||
423
- typeof opts.crop === 'string' ||
424
- typeof opts.quality === 'number' ||
425
- typeof opts.format === 'string';
426
- const qIndex = src.indexOf('?');
427
- const base = qIndex === -1 ? src : src.slice(0, qIndex);
428
- const existingQuery = qIndex === -1 ? '' : src.slice(qIndex + 1);
429
- if (opts.overrideExisting && !hasAnyNewOption) {
430
- return base;
431
- }
432
- const params = new URLSearchParams(opts.overrideExisting ? '' : existingQuery);
433
- const setNum = (key, val) => {
434
- if (typeof val === 'number' && Number.isFinite(val)) {
435
- params.set(key, String(val));
436
- }
437
- };
438
- const setStr = (key, val) => {
439
- if (typeof val === 'string' && val.length > 0) {
440
- params.set(key, val);
441
- }
442
- };
443
- setNum('w', opts.width);
444
- setNum('h', opts.height);
445
- setStr('crop', opts.crop);
446
- setNum('q', opts.quality);
447
- setStr('fm', opts.format);
448
- const query = params.toString();
449
- return query ? `${base}?${query}` : base;
450
- }
451
- async findUploadByFilename(filename) {
452
- try {
453
- if (!filename || typeof filename !== 'string') {
454
- this.logging.log(`findUploadByFilename called with invalid filename: ${String(filename)}`);
455
- return null;
456
- }
457
- const normalizedTarget = filename.trim().toLowerCase().replace(/\.[^.]+$/, '');
458
- const query = encodeURIComponent(normalizedTarget);
459
- this.logging.log(`Searching uploads with query="${normalizedTarget}" for filename="${filename}"`);
460
- const response = await fetch(`${this.baseUrl}/uploads?filter[query]=${query}&page[limit]=100`, {
461
- headers: {
462
- 'Authorization': `Bearer ${this.apiToken}`,
463
- 'X-Api-Version': '3',
464
- 'X-Environment': this.environment,
465
- 'Accept': 'application/json',
466
- },
467
- });
468
- this.handle429(response);
469
- if (!response.ok) {
470
- const errorText = await response.text();
471
- this.logging.error(`Failed to search for existing upload: ${response.status} ${response.statusText} - ${errorText}`);
472
- return null;
473
- }
474
- const data = await response.json().catch((err) => {
475
- this.logging.error(`Failed to parse JSON in findUploadByFilename: ${err.message}`);
476
- return null;
477
- });
478
- const uploads = data?.data || [];
479
- if (!uploads.length) {
480
- this.logging.log(`No uploads returned for query="${normalizedTarget}"`);
481
- return null;
482
- }
483
- const targetFull = filename.trim().toLowerCase();
484
- const match = uploads.find((u) => {
485
- const storedFull = u?.attributes?.filename?.toLowerCase();
486
- if (!storedFull)
487
- return false;
488
- if (storedFull === targetFull)
489
- return true;
490
- const storedNormalized = storedFull.replace(/\.[^.]+$/, '');
491
- if (storedNormalized === normalizedTarget)
492
- return true;
493
- return false;
494
- });
495
- if (match) {
496
- this.logging.log(`Found existing upload for "${filename}" -> asset_id=${match.id}, storedFilename=${match.attributes?.filename}`);
497
- return match;
498
- }
499
- this.logging.log(`No exact filename match found among ${uploads.length} uploads for "${filename}" (query="${normalizedTarget}")`);
500
- return null;
501
- }
502
- catch (err) {
503
- this.logging.error(`Error in findUploadByFilename: ${err?.message ?? String(err)}`);
504
- return null;
505
- }
506
- }
507
- async getItemTypeId(apiKey) {
508
- try {
509
- const res = await fetch(`${this.baseUrl}/item-types`, {
510
- method: "GET",
511
- headers: {
512
- Authorization: `Bearer ${this.apiToken}`,
513
- "X-Api-Version": "3",
514
- "X-Environment": this.environment,
515
- Accept: "application/json",
516
- },
517
- });
518
- this.handle429(res);
519
- if (!res.ok) {
520
- const errorText = await res.text();
521
- throw new Error(`Failed to fetch item types: ${res.status} ${res.statusText} - ${errorText}`);
522
- }
523
- const data = await res.json();
524
- const type = data.data.find((t) => t.attributes.api_key === apiKey);
525
- if (!type)
526
- throw new Error(`Item type "${apiKey}" not found in ${this.environment} - ${JSON.stringify(data)}`);
527
- return type.id;
528
- }
529
- catch (err) {
530
- this.logging.error(`getItemTypeId failed: ${err.message}`);
531
- throw err;
532
- }
533
- }
534
- async getProductBySku(sku) {
535
- try {
536
- const encodedSku = encodeURIComponent(sku);
537
- const res = await fetch(`${this.baseUrl}/items?filter[type]=product&filter[fields][sku][eq]=${encodedSku}&version=current`, {
538
- headers: {
539
- Authorization: `Bearer ${this.apiToken}`,
540
- "X-Api-Version": "3",
541
- "X-Environment": this.environment,
542
- "Content-Type": "application/vnd.api+json",
543
- Accept: "application/json",
544
- },
545
- });
546
- this.handle429(res);
547
- if (!res.ok) {
548
- const errorText = await res.text();
549
- throw new Error(`Failed to fetch product by SKU: ${res.status} ${res.statusText} - ${errorText}`);
550
- }
551
- return await res.json();
552
- }
553
- catch (err) {
554
- this.logging.error(`getProductBySku failed: ${err.message}`);
555
- throw err;
556
- }
557
- }
558
- async createProduct(sku, productTypeId) {
559
- try {
560
- const res = await fetch(`${this.baseUrl}/items`, {
561
- method: "POST",
562
- headers: {
563
- Authorization: `Bearer ${this.apiToken}`,
564
- "X-Api-Version": "3",
565
- "X-Environment": this.environment,
566
- "Content-Type": "application/vnd.api+json",
567
- Accept: "application/json",
568
- },
569
- body: JSON.stringify({
570
- data: {
571
- type: "item",
572
- attributes: { sku },
573
- relationships: {
574
- item_type: { data: { type: "item_type", id: productTypeId } },
575
- },
576
- },
577
- }),
578
- });
579
- this.handle429(res);
580
- if (!res.ok) {
581
- const errorText = await res.text();
582
- throw new Error(`Failed to create product: ${res.status} ${res.statusText} - ${errorText}`);
583
- }
584
- return await res.json();
585
- }
586
- catch (err) {
587
- this.logging.error(`createProduct failed: ${err.message}`);
588
- throw err;
589
- }
590
- }
591
- async updateProductGallery(productId, gallery) {
592
- try {
593
- const res = await fetch(`${this.baseUrl}/items/${productId}`, {
594
- method: "PATCH",
595
- headers: {
596
- Authorization: `Bearer ${this.apiToken}`,
597
- "X-Api-Version": "3",
598
- "X-Environment": this.environment,
599
- "Content-Type": "application/vnd.api+json",
600
- Accept: "application/json",
601
- },
602
- body: JSON.stringify({
603
- data: {
604
- type: "item",
605
- id: productId,
606
- attributes: { gallery },
607
- },
608
- }),
609
- });
610
- this.handle429(res);
611
- if (!res.ok) {
612
- const errorText = await res.text();
613
- throw new Error(`Failed to update product gallery: ${res.status} ${res.statusText} - ${errorText}`);
614
- }
615
- return await res.json();
616
- }
617
- catch (err) {
618
- this.logging.error(`updateProductGallery failed: ${err.message}`);
619
- throw err;
620
- }
621
- }
622
- async updateProductSwatch(productId, uploadId) {
623
- try {
624
- const res = await fetch(`${this.baseUrl}/items/${productId}`, {
625
- method: "PATCH",
626
- headers: {
627
- Authorization: `Bearer ${this.apiToken}`,
628
- "X-Api-Version": "3",
629
- "X-Environment": this.environment,
630
- "Content-Type": "application/vnd.api+json",
631
- Accept: "application/json",
632
- },
633
- body: JSON.stringify({
634
- data: {
635
- type: "item",
636
- id: productId,
637
- attributes: {
638
- swatch: { upload_id: uploadId },
639
- },
640
- },
641
- }),
642
- });
643
- this.handle429(res);
644
- if (!res.ok) {
645
- const errorText = await res.text();
646
- throw new Error(`Failed to update product swatch: ${res.status} ${res.statusText} - ${errorText}`);
647
- }
648
- return await res.json();
649
- }
650
- catch (err) {
651
- this.logging.error(`updateProductSwatch failed: ${err.message}`);
652
- throw err;
653
- }
654
- }
655
- async publishProduct(productId) {
656
- try {
657
- const res = await fetch(`${this.baseUrl}/items/${productId}/publish`, {
658
- method: "PUT",
659
- headers: {
660
- Authorization: `Bearer ${this.apiToken}`,
661
- "X-Api-Version": "3",
662
- "X-Environment": this.environment,
663
- "Content-Type": "application/vnd.api+json",
664
- Accept: "application/json",
665
- },
666
- });
667
- this.handle429(res);
668
- if (!res.ok) {
669
- const errorText = await res.text();
670
- throw new Error(`Failed to publish product: ${res.status} ${res.statusText} - ${errorText}`);
671
- }
672
- return await res.json();
673
- }
674
- catch (err) {
675
- this.logging.error(`publishProduct failed: ${err.message}`);
676
- throw err;
677
- }
678
- }
679
- }
680
- exports.default = DatoHelper;