@code.store/arcxp-sdk-ts 4.49.1 → 5.0.0

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 (194) hide show
  1. package/dist/api/abstract-api.d.ts +2 -2
  2. package/dist/api/author/index.d.ts +2 -2
  3. package/dist/api/author/types.d.ts +32 -1
  4. package/dist/api/content/index.d.ts +4 -4
  5. package/dist/api/content/types.d.ts +3 -4
  6. package/dist/api/content-ops/index.d.ts +2 -2
  7. package/dist/api/custom/index.d.ts +1 -1
  8. package/dist/api/draft/index.d.ts +4 -4
  9. package/dist/api/draft/types.d.ts +4 -4
  10. package/dist/api/global-settings/index.d.ts +2 -2
  11. package/dist/api/identity/index.d.ts +2 -2
  12. package/dist/api/ifx/index.d.ts +2 -2
  13. package/dist/api/index.d.ts +19 -20
  14. package/dist/api/migration-center/index.d.ts +2 -2
  15. package/dist/api/migration-center/types.d.ts +4 -38
  16. package/dist/api/photo-center/index.d.ts +8 -9
  17. package/dist/api/photo-center/types.d.ts +3 -4
  18. package/dist/api/redirect/index.d.ts +2 -2
  19. package/dist/api/retail-events/index.d.ts +2 -2
  20. package/dist/api/sales/index.d.ts +2 -2
  21. package/dist/api/signing-service/index.d.ts +2 -2
  22. package/dist/api/site/index.d.ts +3 -4
  23. package/dist/api/site/types.d.ts +88 -1
  24. package/dist/api/tags/index.d.ts +2 -2
  25. package/dist/api/websked/index.d.ts +2 -2
  26. package/dist/api/ws.client.d.ts +1 -1
  27. package/dist/content-elements/content-elements.d.ts +54 -54
  28. package/dist/content-elements/html/html.processor.d.ts +7 -7
  29. package/dist/content-elements/html/html.utils.d.ts +2 -2
  30. package/dist/content-elements/html/index.d.ts +3 -3
  31. package/dist/content-elements/index.d.ts +2 -2
  32. package/dist/content-elements/types.d.ts +4 -0
  33. package/dist/index.cjs +2082 -0
  34. package/dist/index.cjs.map +1 -0
  35. package/dist/index.d.ts +9 -20
  36. package/dist/index.js +2048 -61
  37. package/dist/index.js.map +1 -1
  38. package/dist/lib/platform/index.d.ts +6 -0
  39. package/dist/lib/platform/node.d.ts +6 -0
  40. package/dist/mapper/doc.d.ts +26 -25
  41. package/dist/mapper/index.d.ts +2 -2
  42. package/dist/mapper/story.d.ts +4 -4
  43. package/dist/types/{story.d.ts → ans-types.d.ts} +378 -85
  44. package/dist/types/index.d.ts +15 -7
  45. package/dist/utils/arc/ans.d.ts +2 -2
  46. package/dist/utils/arc/content.d.ts +1 -1
  47. package/dist/utils/arc/index.d.ts +5 -3
  48. package/dist/utils/arc/section.d.ts +33 -0
  49. package/dist/utils/decorator.d.ts +1 -1
  50. package/package.json +26 -10
  51. package/dist/api/abstract-api.js +0 -61
  52. package/dist/api/abstract-api.js.map +0 -1
  53. package/dist/api/author/index.js +0 -19
  54. package/dist/api/author/index.js.map +0 -1
  55. package/dist/api/author/types.js +0 -3
  56. package/dist/api/author/types.js.map +0 -1
  57. package/dist/api/content/index.js +0 -29
  58. package/dist/api/content/index.js.map +0 -1
  59. package/dist/api/content/types.js +0 -3
  60. package/dist/api/content/types.js.map +0 -1
  61. package/dist/api/content-ops/index.js +0 -27
  62. package/dist/api/content-ops/index.js.map +0 -1
  63. package/dist/api/content-ops/types.js +0 -3
  64. package/dist/api/content-ops/types.js.map +0 -1
  65. package/dist/api/custom/index.js +0 -18
  66. package/dist/api/custom/index.js.map +0 -1
  67. package/dist/api/draft/index.js +0 -63
  68. package/dist/api/draft/index.js.map +0 -1
  69. package/dist/api/draft/types.js +0 -3
  70. package/dist/api/draft/types.js.map +0 -1
  71. package/dist/api/error.js +0 -26
  72. package/dist/api/error.js.map +0 -1
  73. package/dist/api/global-settings/index.js +0 -19
  74. package/dist/api/global-settings/index.js.map +0 -1
  75. package/dist/api/global-settings/types.js +0 -3
  76. package/dist/api/global-settings/types.js.map +0 -1
  77. package/dist/api/identity/index.js +0 -35
  78. package/dist/api/identity/index.js.map +0 -1
  79. package/dist/api/identity/types.js +0 -3
  80. package/dist/api/identity/types.js.map +0 -1
  81. package/dist/api/ifx/index.js +0 -94
  82. package/dist/api/ifx/index.js.map +0 -1
  83. package/dist/api/ifx/types.js +0 -3
  84. package/dist/api/ifx/types.js.map +0 -1
  85. package/dist/api/index.js +0 -49
  86. package/dist/api/index.js.map +0 -1
  87. package/dist/api/migration-center/index.js +0 -45
  88. package/dist/api/migration-center/index.js.map +0 -1
  89. package/dist/api/migration-center/types.js +0 -41
  90. package/dist/api/migration-center/types.js.map +0 -1
  91. package/dist/api/photo-center/index.js +0 -64
  92. package/dist/api/photo-center/index.js.map +0 -1
  93. package/dist/api/photo-center/types.js +0 -3
  94. package/dist/api/photo-center/types.js.map +0 -1
  95. package/dist/api/redirect/index.js +0 -23
  96. package/dist/api/redirect/index.js.map +0 -1
  97. package/dist/api/redirect/types.js +0 -3
  98. package/dist/api/redirect/types.js.map +0 -1
  99. package/dist/api/retail-events/index.js +0 -18
  100. package/dist/api/retail-events/index.js.map +0 -1
  101. package/dist/api/sales/index.js +0 -25
  102. package/dist/api/sales/index.js.map +0 -1
  103. package/dist/api/sales/types.js +0 -3
  104. package/dist/api/sales/types.js.map +0 -1
  105. package/dist/api/signing-service/index.js +0 -15
  106. package/dist/api/signing-service/index.js.map +0 -1
  107. package/dist/api/signing-service/types.js +0 -3
  108. package/dist/api/signing-service/types.js.map +0 -1
  109. package/dist/api/site/index.js +0 -44
  110. package/dist/api/site/index.js.map +0 -1
  111. package/dist/api/site/types.js +0 -3
  112. package/dist/api/site/types.js.map +0 -1
  113. package/dist/api/tags/index.js +0 -36
  114. package/dist/api/tags/index.js.map +0 -1
  115. package/dist/api/tags/types.js +0 -3
  116. package/dist/api/tags/types.js.map +0 -1
  117. package/dist/api/websked/index.js +0 -47
  118. package/dist/api/websked/index.js.map +0 -1
  119. package/dist/api/websked/types.js +0 -3
  120. package/dist/api/websked/types.js.map +0 -1
  121. package/dist/api/ws.client.js +0 -68
  122. package/dist/api/ws.client.js.map +0 -1
  123. package/dist/content-elements/content-elements.js +0 -235
  124. package/dist/content-elements/content-elements.js.map +0 -1
  125. package/dist/content-elements/html/html.constants.js +0 -40
  126. package/dist/content-elements/html/html.constants.js.map +0 -1
  127. package/dist/content-elements/html/html.processor.js +0 -370
  128. package/dist/content-elements/html/html.processor.js.map +0 -1
  129. package/dist/content-elements/html/html.utils.js +0 -79
  130. package/dist/content-elements/html/html.utils.js.map +0 -1
  131. package/dist/content-elements/html/index.js +0 -41
  132. package/dist/content-elements/html/index.js.map +0 -1
  133. package/dist/content-elements/index.js +0 -42
  134. package/dist/content-elements/index.js.map +0 -1
  135. package/dist/mapper/doc.js +0 -146
  136. package/dist/mapper/doc.js.map +0 -1
  137. package/dist/mapper/index.js +0 -8
  138. package/dist/mapper/index.js.map +0 -1
  139. package/dist/mapper/story.js +0 -111
  140. package/dist/mapper/story.js.map +0 -1
  141. package/dist/scripts/json-schema-to-ts.js +0 -8
  142. package/dist/scripts/json-schema-to-ts.js.map +0 -1
  143. package/dist/tests/ans/mapper.test.d.ts +0 -1
  144. package/dist/tests/ans/mapper.test.js +0 -93
  145. package/dist/tests/ans/mapper.test.js.map +0 -1
  146. package/dist/tests/api/basic.test.d.ts +0 -1
  147. package/dist/tests/api/basic.test.js +0 -20
  148. package/dist/tests/api/basic.test.js.map +0 -1
  149. package/dist/tests/api/retry.test.d.ts +0 -1
  150. package/dist/tests/api/retry.test.js +0 -51
  151. package/dist/tests/api/retry.test.js.map +0 -1
  152. package/dist/tests/api/utils.test.d.ts +0 -1
  153. package/dist/tests/api/utils.test.js +0 -255
  154. package/dist/tests/api/utils.test.js.map +0 -1
  155. package/dist/tests/content-elements/html.processor.test.d.ts +0 -1
  156. package/dist/tests/content-elements/html.processor.test.js +0 -35
  157. package/dist/tests/content-elements/html.processor.test.js.map +0 -1
  158. package/dist/types/author.d.ts +0 -1640
  159. package/dist/types/author.js +0 -8
  160. package/dist/types/author.js.map +0 -1
  161. package/dist/types/content-elements.d.ts +0 -4
  162. package/dist/types/content-elements.js +0 -3
  163. package/dist/types/content-elements.js.map +0 -1
  164. package/dist/types/gallery.d.ts +0 -52
  165. package/dist/types/gallery.js +0 -3
  166. package/dist/types/gallery.js.map +0 -1
  167. package/dist/types/index.js +0 -44
  168. package/dist/types/index.js.map +0 -1
  169. package/dist/types/section.d.ts +0 -88
  170. package/dist/types/section.js +0 -3
  171. package/dist/types/section.js.map +0 -1
  172. package/dist/types/story.js +0 -8
  173. package/dist/types/story.js.map +0 -1
  174. package/dist/types/utils.js +0 -3
  175. package/dist/types/utils.js.map +0 -1
  176. package/dist/types/video.d.ts +0 -1425
  177. package/dist/types/video.js +0 -8
  178. package/dist/types/video.js.map +0 -1
  179. package/dist/utils/arc/ans.js +0 -14
  180. package/dist/utils/arc/ans.js.map +0 -1
  181. package/dist/utils/arc/content.js +0 -79
  182. package/dist/utils/arc/content.js.map +0 -1
  183. package/dist/utils/arc/id.js +0 -40
  184. package/dist/utils/arc/id.js.map +0 -1
  185. package/dist/utils/arc/index.js +0 -45
  186. package/dist/utils/arc/index.js.map +0 -1
  187. package/dist/utils/cache.js +0 -63
  188. package/dist/utils/cache.js.map +0 -1
  189. package/dist/utils/decorator.js +0 -20
  190. package/dist/utils/decorator.js.map +0 -1
  191. package/dist/utils/duration.js +0 -21
  192. package/dist/utils/duration.js.map +0 -1
  193. package/dist/utils/index.js +0 -52
  194. package/dist/utils/index.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,64 +1,2051 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
1
+ import axios from 'axios';
2
+ import * as rateLimit from 'axios-rate-limit';
3
+ import axiosRetry from 'axios-retry';
4
+ import * as ws from 'ws';
5
+ import FormData from 'form-data';
6
+ import encode from 'base32-encode';
7
+ import { v5 } from 'uuid';
8
+ import assert from 'node:assert';
9
+ import { TextNode, HTMLElement, CommentNode, parse } from 'node-html-parser';
10
+ import { decode } from 'html-entities';
11
+
12
+ const safeJSONStringify = (data) => {
13
+ try {
14
+ return JSON.stringify(data) || '';
15
+ }
16
+ catch {
17
+ return '';
18
+ }
19
+ };
20
+ const AxiosResponseErrorInterceptor = (errorConstructor) => {
21
+ return [
22
+ (response) => response,
23
+ (error) => {
24
+ throw errorConstructor(error);
25
+ },
26
+ ];
27
+ };
28
+
29
+ class ArcError extends Error {
30
+ constructor(service, e) {
31
+ const ratelimitRemaining = e.response?.headers['arcpub-ratelimit-remaining'];
32
+ const ratelimitReset = e.response?.headers['arcpub-ratelimit-reset'];
33
+ const data = {
34
+ name: `${service}Error`,
35
+ message: e.message,
36
+ responseData: e.response?.data,
37
+ responseStatus: e.response?.status,
38
+ responseConfig: e.response?.config,
39
+ ratelimitRemaining,
40
+ ratelimitReset,
41
+ service,
42
+ };
43
+ const message = safeJSONStringify(data);
44
+ super(message);
45
+ Object.assign(this, data);
46
+ this.stack = e.stack;
47
+ }
48
+ }
49
+
50
+ class ArcAbstractAPI {
51
+ constructor(options) {
52
+ this.name = this.constructor.name;
53
+ this.token = '';
54
+ this.host = '';
55
+ this.headers = {
56
+ Authorization: '',
57
+ };
58
+ this.host = `api.${options.credentials.organizationName}.arcpublishing.com`;
59
+ this.token = `Bearer ${options.credentials.accessToken}`;
60
+ this.headers.Authorization = this.token;
61
+ const instance = axios.create({
62
+ baseURL: `https://${this.host}/${options.apiPath}`,
63
+ headers: this.headers,
64
+ });
65
+ // apply rate limiting
66
+ this.client = rateLimit.default(instance, { maxRPS: options.maxRPS || 10 });
67
+ // apply retry
68
+ const retry = typeof axiosRetry === 'function' ? axiosRetry : axiosRetry.default;
69
+ retry(this.client, {
70
+ retries: 5,
71
+ retryDelay: axiosRetry.exponentialDelay,
72
+ retryCondition: (err) => this.retryCondition(err),
73
+ });
74
+ // wrap response errors
75
+ this.client.interceptors.response.use(...AxiosResponseErrorInterceptor((e) => {
76
+ if (e instanceof ArcError)
77
+ return e;
78
+ return new ArcError(this.name, e);
79
+ }));
80
+ }
81
+ setMaxRPS(rps) {
82
+ this.client.setMaxRPS(rps);
83
+ }
84
+ retryCondition(error) {
85
+ const status = error.response?.status;
86
+ switch (status) {
87
+ case axios.HttpStatusCode.RequestTimeout:
88
+ case axios.HttpStatusCode.TooManyRequests:
89
+ case axios.HttpStatusCode.InternalServerError:
90
+ case axios.HttpStatusCode.BadGateway:
91
+ case axios.HttpStatusCode.ServiceUnavailable:
92
+ case axios.HttpStatusCode.GatewayTimeout:
93
+ return true;
94
+ default:
95
+ return false;
96
+ }
97
+ }
98
+ }
99
+
100
+ class ArcAuthor extends ArcAbstractAPI {
101
+ constructor(options) {
102
+ super({ ...options, apiPath: 'author' });
103
+ }
104
+ async listAuthors(params) {
105
+ const { data } = await this.client.get('/v2/author-service', { params });
106
+ return data;
107
+ }
108
+ async delete(userId) {
109
+ const { data } = await this.client.delete(`/v2/author-service/${userId}`);
110
+ return data;
111
+ }
112
+ }
113
+
114
+ class ArcContentOps extends ArcAbstractAPI {
115
+ constructor(options) {
116
+ super({ ...options, apiPath: 'contentops/v1' });
117
+ }
118
+ async schedulePublish(payload) {
119
+ const { data } = await this.client.put('/publish', payload);
120
+ return data;
121
+ }
122
+ async scheduleUnpublish(payload) {
123
+ const { data } = await this.client.put('/unpublish', payload);
124
+ return data;
125
+ }
126
+ async unscheduleUnpublish(payload) {
127
+ const { data } = await this.client.put('/unschedule_unpublish', payload);
128
+ return data;
129
+ }
130
+ async unschedulePublish(payload) {
131
+ const { data } = await this.client.put('/unschedule_publish', payload);
132
+ return data;
133
+ }
134
+ }
135
+
136
+ class ArcContent extends ArcAbstractAPI {
137
+ constructor(options) {
138
+ super({ ...options, apiPath: 'content/v4' });
139
+ }
140
+ async getStory(params) {
141
+ const { data } = await this.client.get('/stories', { params });
142
+ return data;
143
+ }
144
+ async search(params) {
145
+ const { data } = await this.client.get('/search', { params });
146
+ return data;
147
+ }
148
+ async scan(params) {
149
+ const { data } = await this.client.get('/scan', { params });
150
+ return data;
151
+ }
152
+ async getStoriesByIds(params) {
153
+ const { data } = await this.client.get('/ids', {
154
+ params: { ...params, ids: params.ids.join(',') },
155
+ });
156
+ return data;
157
+ }
158
+ }
159
+
160
+ class Custom extends ArcAbstractAPI {
161
+ constructor(options) {
162
+ super({ ...options, apiPath: '' });
163
+ }
164
+ async request(endpoint, config = {}) {
165
+ const response = await this.client.request({
166
+ url: endpoint,
167
+ ...config,
168
+ });
169
+ return response;
170
+ }
171
+ }
172
+
173
+ class ArcDraft extends ArcAbstractAPI {
174
+ constructor(options) {
175
+ super({ ...options, apiPath: 'draft/v1' });
176
+ }
177
+ async generateId(id) {
178
+ const { data } = await this.client.get('/arcuuid', { params: { id } });
179
+ return data.id;
180
+ }
181
+ async createDocument(ans, type = 'story') {
182
+ const { data } = await this.client.post(`/${type}`, ans);
183
+ return data;
184
+ }
185
+ async publishDocument(id, type = 'story') {
186
+ const { data } = await this.client.post(`/${type}/${id}/revision/published`);
187
+ return data;
188
+ }
189
+ async unpublishDocument(id, type = 'story') {
190
+ const { data } = await this.client.delete(`/${type}/${id}/revision/published`);
191
+ return data;
192
+ }
193
+ async deleteDocument(id, type = 'story') {
194
+ const { data } = await this.client.delete(`/${type}/${id}`);
195
+ return data;
196
+ }
197
+ async getPublishedRevision(id, type = 'story') {
198
+ const { data } = await this.client.get(`/${type}/${id}/revision/published`);
199
+ return data;
200
+ }
201
+ async getDraftRevision(id, type = 'story') {
202
+ const { data } = await this.client.get(`/${type}/${id}/revision/draft`);
203
+ return data;
204
+ }
205
+ async getCirculations(id, type = 'story', after) {
206
+ const { data } = await this.client.get(`/${type}/${id}/circulation`, { params: { after } });
207
+ return data;
208
+ }
209
+ async getRevisions(id, type = 'story', after) {
210
+ const { data } = await this.client.get(`/${type}/${id}/revision`, { params: { after } });
211
+ return data;
212
+ }
213
+ async getRevision(id, revisionId, type = 'story') {
214
+ const { data } = await this.client.get(`/${type}/${id}/revision/${revisionId}`);
215
+ return data;
216
+ }
217
+ async createRedirect(website, websiteUrl, payload) {
218
+ const { data } = await this.client.post(`/redirect/${website}/${websiteUrl}`, payload);
219
+ return data;
220
+ }
221
+ async getRedirect(website, websiteUrl) {
222
+ const { data } = await this.client.get(`/redirect/${website}/${websiteUrl}`);
223
+ return data;
224
+ }
225
+ async updateDraftRevision(id, payload, type = 'story') {
226
+ const { data } = await this.client.put(`/${type}/${id}/revision/draft`, payload);
227
+ return data;
228
+ }
229
+ }
230
+
231
+ class GlobalSettings extends ArcAbstractAPI {
232
+ constructor(options) {
233
+ super({ ...options, apiPath: 'settings/v1' });
234
+ }
235
+ async getDistributors(params) {
236
+ const { data } = await this.client.get('/distributor', { params });
237
+ return data;
238
+ }
239
+ async createDistributors(payload) {
240
+ const { data } = await this.client.post('/distributor', payload);
241
+ return data;
242
+ }
243
+ }
244
+
245
+ class ArcIdentity extends ArcAbstractAPI {
246
+ constructor(options) {
247
+ super({ ...options, apiPath: 'identity/api/v1' });
248
+ }
249
+ async migrateBatch(payload) {
250
+ const { data } = await this.client.post('/migrate', payload);
251
+ return data;
252
+ }
253
+ async *migrateBatchGenerator(payload, batchSize = 100) {
254
+ const copy = [...payload.records];
255
+ while (copy.length) {
256
+ const records = copy.splice(0, batchSize);
257
+ const response = await this.migrateBatch({ records });
258
+ yield response;
259
+ }
260
+ }
261
+ async getUser(id) {
262
+ const { data } = await this.client.get(`/user?search=uuid=${id}`);
263
+ return data;
264
+ }
265
+ async getUserByEmail(email) {
266
+ const { data } = await this.client.get(`/user?search=email=${email}`);
267
+ return data;
268
+ }
269
+ async updateUserProfile(id, payload) {
270
+ const { data } = await this.client.patch(`/profile/${id}`, payload);
271
+ return data;
272
+ }
273
+ }
274
+
275
+ const importNodeModule = async (moduleId) => await import(moduleId);
276
+ const modules = {
277
+ // make it like that so static analyzer of webpack won't bundle it
278
+ fs: () => importNodeModule('node:fs'),
279
+ path: () => importNodeModule('node:path'),
280
+ form_data: () => importNodeModule('form-data'),
281
+ };
282
+
283
+ var platform = {
284
+ ...modules,
285
+ };
286
+
287
+ class ArcIFX extends ArcAbstractAPI {
288
+ constructor(options) {
289
+ super({ ...options, apiPath: 'ifx/api/v1' });
290
+ }
291
+ async createIntegration(payload) {
292
+ await this.client.post('/admin/integration', payload);
293
+ }
294
+ async updateIntegration(integrationName, payload) {
295
+ await this.client.put(`/admin/integration/${integrationName}`, payload);
296
+ }
297
+ async deleteIntegration(integrationName, token) {
298
+ await this.client.delete(`/admin/integration/${integrationName}`, { params: { token } });
299
+ }
300
+ async generateDeleteIntegrationToken(integrationName) {
301
+ const response = await this.client.get(`/admin/integration/${integrationName}/token`);
302
+ return response.data;
303
+ }
304
+ async getIntegrations() {
305
+ const { data } = await this.client.get('/admin/integrations');
306
+ return data;
307
+ }
308
+ async getJobs(integrationName) {
309
+ const { data } = await this.client.get(`/admin/jobs/status/${integrationName}`);
310
+ return data;
311
+ }
312
+ async getStatus(integrationName) {
313
+ const { data } = await this.client.get(`/admin/integration/${integrationName}/provisionStatus`);
314
+ return data;
315
+ }
316
+ async initializeQuery(integrationName, query) {
317
+ const { data } = await this.client.get(`/admin/logs/integration/${integrationName}?${query}`);
318
+ return data;
319
+ }
320
+ async getLogs(queryId, raw = true) {
321
+ const { data } = await this.client.get('/admin/logs/results', { params: { queryId, raw } });
322
+ return data;
323
+ }
324
+ async subscribe(payload) {
325
+ const { data } = await this.client.post('/admin/events/subscriptions', payload);
326
+ return data;
327
+ }
328
+ async updateSubscription(payload) {
329
+ const { data } = await this.client.put('/admin/events/subscriptions', payload);
330
+ return data;
331
+ }
332
+ async getSubscriptions() {
333
+ const { data } = await this.client.get('/admin/events/subscriptions');
334
+ return data;
335
+ }
336
+ async addSecret(payload) {
337
+ const { data } = await this.client.post(`/admin/secret?integrationName=${payload.integrationName}`, {
338
+ secretName: payload.secretName,
339
+ secretValue: payload.secretValue,
340
+ });
341
+ return data;
342
+ }
343
+ async getSecrets(integrationName) {
344
+ const { data } = await this.client.get(`/admin/secret?integrationName=${integrationName}`);
345
+ return data;
346
+ }
347
+ async getBundles(integrationName) {
348
+ const { data } = await this.client.get(`/admin/bundles/${integrationName}`);
349
+ return data;
350
+ }
351
+ async uploadBundle(integrationName, name, bundlePath) {
352
+ const fs = await platform.fs();
353
+ const FormData = await platform.form_data();
354
+ const form = new FormData();
355
+ console.log('platform', platform);
356
+ console.log(form);
357
+ const bundle = fs.createReadStream(bundlePath);
358
+ form.append('bundle', bundle);
359
+ form.append('name', name);
360
+ const { data } = await this.client.post(`/admin/bundles/${integrationName}`, form, {
361
+ headers: form.getHeaders(),
362
+ });
363
+ return data;
364
+ }
365
+ async deployBundle(integrationName, name) {
366
+ const { data } = await this.client.post(`/admin/bundles/${integrationName}/deploy/${name}`);
367
+ return data;
368
+ }
369
+ async promoteBundle(integrationName, version) {
370
+ const { data } = await this.client.post(`/admin/bundles/${integrationName}/promote/${version}`);
371
+ return data;
372
+ }
373
+ }
374
+
375
+ class ArcMigrationCenter extends ArcAbstractAPI {
376
+ constructor(options) {
377
+ super({ ...options, apiPath: 'migrations/v3' });
378
+ }
379
+ async summary(params) {
380
+ const { data, headers } = await this.client.get('/report/summary', { params });
381
+ const nextFromId = headers['amc-record-id'];
382
+ return { records: data, nextFromId };
383
+ }
384
+ async detailed(params) {
385
+ const { data } = await this.client.get('/report/detail', { params });
386
+ return data;
387
+ }
388
+ async count(params) {
389
+ const { data } = await this.client.get('/report/status/count', {
390
+ params: {
391
+ startDate: params?.startDate?.toISOString(),
392
+ endDate: params?.endDate?.toISOString(),
393
+ },
394
+ });
395
+ return data;
396
+ }
397
+ async postAns(params, payload) {
398
+ const { data } = await this.client.post('/content/ans', payload, { params });
399
+ return data;
400
+ }
401
+ async getAns(params) {
402
+ const { data } = await this.client.get('/content/ans', { params });
403
+ return data;
404
+ }
405
+ async getRemainingTime(params) {
406
+ const { data } = await this.client.get('/report/remaining-time', { params });
407
+ return data;
408
+ }
409
+ async getRecentGroupIds() {
410
+ const { data } = await this.client.get('/report/group-ids');
411
+ return data;
412
+ }
413
+ }
414
+
415
+ class ArcProtoCenter extends ArcAbstractAPI {
416
+ constructor(options) {
417
+ super({ ...options, apiPath: 'photo/api' });
418
+ }
419
+ async getImageDataById(imageId) {
420
+ const { data } = await this.client.get(`/v2/photos/${imageId}`);
421
+ return data;
422
+ }
423
+ async uploadImageANS(image) {
424
+ const FormData = await platform.form_data();
425
+ const form = new FormData();
426
+ form.append('ans', JSON.stringify(image), {
427
+ filename: 'ans.json',
428
+ contentType: 'application/json',
429
+ });
430
+ const { data } = await this.client.post('/v2/photos', form, { headers: form.getHeaders() });
431
+ return data;
432
+ }
433
+ async uploadImageStream(readableStream, options) {
434
+ const path = await platform.path();
435
+ const FormData = await platform.form_data();
436
+ const form = new FormData();
437
+ const contentType = options?.contentType ?? 'application/octet-stream';
438
+ const filename = path.basename(String(options?.filename || readableStream.path || 'file.jpg'));
439
+ form.append('file', readableStream, {
440
+ filename: filename,
441
+ contentType,
442
+ });
443
+ const { data } = await this.client.post('/v2/photos', form, { headers: form.getHeaders() });
444
+ return data;
445
+ }
446
+ async deleteImage(imageId) {
447
+ const { data } = await this.client.delete(`/v2/photos/${imageId}`);
448
+ return data;
449
+ }
450
+ async deleteGallery(galleryId) {
451
+ const { data } = await this.client.delete(`/v2/galleries/${galleryId}`);
452
+ return data;
453
+ }
454
+ async getImages(params) {
455
+ const { data } = await this.client.get('/v2/photos', { params });
456
+ return data;
457
+ }
458
+ async getGalleries(params) {
459
+ const { data } = await this.client.get('/v2/galleries', { params });
460
+ return data;
461
+ }
462
+ async getGallery(galleryId) {
463
+ const { data } = await this.client.get(`/v2/galleries/${galleryId}`);
464
+ return data;
465
+ }
466
+ async updateImage(imageId, photoDto) {
467
+ const { data } = await this.client.put(`/v2/photos/${imageId}`, photoDto);
468
+ return data;
469
+ }
470
+ }
471
+
472
+ class ArcRedirect extends ArcAbstractAPI {
473
+ constructor(options) {
474
+ super({ ...options, apiPath: 'delivery-api/v1/cloudlet/redirector/site' });
475
+ }
476
+ async getRedirects(orgSiteEnv) {
477
+ const { data } = await this.client.get(`/${orgSiteEnv}/rule?limit=1000`);
478
+ return data;
479
+ }
480
+ async updateArcRedirectRule(orgSiteEnv, redirectID, redirectRuleContent) {
481
+ const { data } = await this.client.put(`/${orgSiteEnv}/rule/${redirectID}`, redirectRuleContent);
482
+ return data;
483
+ }
484
+ async activateRedirectsVersion(orgSiteEnv) {
485
+ const { data } = await this.client.post(`/${orgSiteEnv}/version`);
486
+ return data;
487
+ }
488
+ }
489
+
490
+ class WsClient {
491
+ constructor(address, options) {
492
+ this.address = address;
493
+ this.options = options;
494
+ this._closing = false;
495
+ }
496
+ async connect() {
497
+ if (this.socket && this.socket.readyState === this.socket.OPEN)
498
+ return;
499
+ const socket = new ws.WebSocket(this.address, this.options);
500
+ this._closing = false;
501
+ socket.onclose = (event) => this.close(event);
502
+ await new Promise((resolve, reject) => {
503
+ socket.onerror = (error) => reject(error);
504
+ socket.onopen = () => resolve(true);
505
+ });
506
+ socket.onmessage = ({ data }) => {
507
+ let message;
508
+ try {
509
+ message = JSON.parse(data.toString());
510
+ }
511
+ catch {
512
+ throw new Error('failed to parse message');
513
+ }
514
+ this.onMessage?.(message);
515
+ };
516
+ this.socket = socket;
517
+ this.onOpen?.();
518
+ }
519
+ close(event) {
520
+ if (this._closing)
521
+ return;
522
+ this._closing = true;
523
+ this.socket?.close();
524
+ this.onClose?.(event);
525
+ }
526
+ async send(data) {
527
+ this.throwIfNotOpen();
528
+ await new Promise((resolve, reject) => {
529
+ this.socket.send(data, (error) => {
530
+ error ? reject(error) : resolve(undefined);
531
+ });
532
+ });
533
+ }
534
+ throwIfNotOpen() {
535
+ if (!this.socket) {
536
+ throw new Error('Client is not connected');
537
+ }
538
+ const { readyState, OPEN } = this.socket;
539
+ if (readyState === OPEN)
540
+ return;
541
+ if (readyState < OPEN) {
542
+ throw new Error('socket is still connecting');
543
+ }
544
+ if (readyState > OPEN) {
545
+ throw new Error('socket was closed');
546
+ }
547
+ }
548
+ }
549
+
550
+ class ArcRetailEvents {
551
+ constructor(options) {
552
+ this.options = options;
553
+ }
554
+ createWsClient(index = '0') {
555
+ const address = `wss://api.${this.options.credentials.organizationName}.arcpublishing.com/retail/api/v1/event/stream/${index}`;
556
+ const headers = {
557
+ Authorization: `Bearer ${this.options.credentials.accessToken}`,
558
+ };
559
+ return new WsClient(address, { headers });
560
+ }
561
+ }
562
+
563
+ class ArcSales extends ArcAbstractAPI {
564
+ constructor(options) {
565
+ super({ ...options, apiPath: 'sales/api/v1' });
566
+ }
567
+ async migrate(payload) {
568
+ const form = new FormData();
569
+ form.append('file', JSON.stringify(payload), { filename: 'subs.json', contentType: 'application/json' });
570
+ const { data } = await this.client.post('/migrate', form, {
571
+ headers: {
572
+ ...form.getHeaders(),
573
+ },
574
+ });
575
+ return data;
576
+ }
577
+ }
578
+
579
+ class ArcSigningService extends ArcAbstractAPI {
580
+ constructor(options) {
581
+ super({ ...options, apiPath: 'signing-service' });
582
+ }
583
+ async sign(service, serviceVersion, imageId) {
584
+ const { data } = await this.client.get(`/v2/sign/${service}/${serviceVersion}?value=${encodeURI(imageId)}`);
585
+ return data;
586
+ }
587
+ }
588
+
589
+ class ArcSite extends ArcAbstractAPI {
590
+ constructor(options) {
591
+ super({ ...options, apiPath: 'site/v3' });
592
+ }
593
+ async getSections(params) {
594
+ const { data } = await this.client.get(`/website/${params.website}/section`, {
595
+ params: { _website: params.website, ...params },
596
+ });
597
+ return data;
598
+ }
599
+ async getSection(id, website) {
600
+ const { data } = await this.client.get(`/website/${website}/section?_id=${id}`);
601
+ return data;
602
+ }
603
+ async deleteSection(id, website) {
604
+ await this.client.delete(`/website/${website}/section?_id=${id}`);
605
+ }
606
+ async putSection(section) {
607
+ const { data } = await this.client.put(`/website/${section.website}/section?_id=${section._id}`, section);
608
+ return data;
609
+ }
610
+ async getWebsites() {
611
+ const { data } = await this.client.get('/website');
612
+ return data;
613
+ }
614
+ async putLink(link) {
615
+ const { data } = await this.client.put(`/website/${link._website}/link/${link._id}`, link);
616
+ return data;
617
+ }
618
+ async deleteLink(id, website) {
619
+ const { data } = await this.client.delete(`/website/${website}/link/${id}`);
620
+ return data;
621
+ }
622
+ async getLinks(params) {
623
+ const { data } = await this.client.get(`/website/${params.website}/link`, { params });
624
+ return data;
625
+ }
626
+ }
627
+
628
+ class ArcTags extends ArcAbstractAPI {
629
+ constructor(options) {
630
+ super({ ...options, apiPath: 'tags' });
631
+ }
632
+ async getAllTags(params) {
633
+ const { data } = await this.client.get('/', { params });
634
+ return data;
635
+ }
636
+ /*
637
+ * @Deprecated
638
+ * May return incorrect results
639
+ * Use searchTagsV2 instead
640
+ */
641
+ async searchTags(params) {
642
+ const { data } = await this.client.get('/search', { params });
643
+ return data;
644
+ }
645
+ async searchTagsV2(params) {
646
+ const { data } = await this.client.get('/v2/search', { params });
647
+ return data;
648
+ }
649
+ async addTags(payload) {
650
+ const { data } = await this.client.post('/add', payload);
651
+ return data;
652
+ }
653
+ async deleteTags(payload) {
654
+ const { data } = await this.client.post('/delete', payload);
655
+ return data;
656
+ }
657
+ }
658
+
659
+ class ArcWebsked extends ArcAbstractAPI {
660
+ constructor(options) {
661
+ super({ ...options, apiPath: 'websked' });
662
+ }
663
+ async reportStatusChange(payload) {
664
+ const { data } = await this.client.post('/tasks/workflowStatusChange', payload);
665
+ return data;
666
+ }
667
+ async createTask(payload) {
668
+ const { data } = await this.client.post('/tasks', payload);
669
+ return data;
670
+ }
671
+ async getEditionTimes(publicationId, startDate, endDate, numEditions = 1) {
672
+ const { data } = await this.client.get(`/publications/${publicationId}/editionTimes`, {
673
+ params: { startDate, endDate, numEditions },
674
+ });
675
+ return data;
676
+ }
677
+ async getSectionStories(publicationId, sectionId, timestamp, includeStories = true) {
678
+ const { data } = await this.client.get(`/publications/${publicationId}/sections/${sectionId}/editions/${timestamp}`, { params: { includeStories } });
679
+ return data;
680
+ }
681
+ async getSectionEditions(publicationId, sectionId, startDate, numEditions = 100) {
682
+ const { data } = await this.client.get(`/publications/${publicationId}/sections/${sectionId}/editions`, {
683
+ params: { startDate, numEditions },
684
+ });
685
+ return data;
686
+ }
687
+ async getPublications(nameRegex) {
688
+ const { data } = await this.client.get('/publications', { params: { nameRegex } });
689
+ return data;
690
+ }
691
+ async getPublicationById(publicationId) {
692
+ const { data } = await this.client.get(`/publications/${publicationId}`);
693
+ return data;
694
+ }
695
+ async getStatuses() {
696
+ const { data } = await this.client.get('/statuses');
697
+ return data;
698
+ }
699
+ }
700
+
701
+ const ArcAPI = (options) => {
702
+ const API = {
703
+ Author: new ArcAuthor(options),
704
+ Draft: new ArcDraft(options),
705
+ Identity: new ArcIdentity(options),
706
+ IFX: new ArcIFX(options),
707
+ Redirect: new ArcRedirect(options),
708
+ MigrationCenter: new ArcMigrationCenter(options),
709
+ Sales: new ArcSales(options),
710
+ Site: new ArcSite(options),
711
+ Websked: new ArcWebsked(options),
712
+ Content: new ArcContent(options),
713
+ SigningService: new ArcSigningService(options),
714
+ PhotoCenter: new ArcProtoCenter(options),
715
+ GlobalSettings: new GlobalSettings(options),
716
+ Tags: new ArcTags(options),
717
+ ContentOps: new ArcContentOps(options),
718
+ RetailEvents: new ArcRetailEvents(options),
719
+ Custom: new Custom(options),
720
+ };
721
+ API.MigrationCenter.setMaxRPS(12);
722
+ API.Draft.setMaxRPS(4);
723
+ API.Content.setMaxRPS(3);
724
+ return API;
725
+ };
726
+
727
+ /* eslint-disable */
728
+ /**
729
+ * This file was automatically generated by json-schema-to-typescript.
730
+ * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
731
+ * and run json-schema-to-typescript to regenerate this file.
732
+ */
733
+
734
+ var ansTypes = /*#__PURE__*/Object.freeze({
735
+ __proto__: null
736
+ });
737
+
738
+ var utils = /*#__PURE__*/Object.freeze({
739
+ __proto__: null
740
+ });
741
+
742
+ var ANSType;
743
+ (function (ANSType) {
744
+ ANSType["Story"] = "story";
745
+ ANSType["Video"] = "video";
746
+ ANSType["Tag"] = "tag";
747
+ ANSType["Author"] = "author";
748
+ ANSType["Gallery"] = "gallery";
749
+ ANSType["Image"] = "image";
750
+ ANSType["Redirect"] = "redirect";
751
+ })(ANSType || (ANSType = {}));
752
+ var MigrationStatus;
753
+ (function (MigrationStatus) {
754
+ MigrationStatus["Success"] = "Success";
755
+ MigrationStatus["Queued"] = "Queued";
756
+ MigrationStatus["Circulated"] = "Circulated";
757
+ MigrationStatus["Published"] = "Published";
758
+ MigrationStatus["Scheduled"] = "Scheduled";
759
+ MigrationStatus["FailVideo"] = "FailVideo";
760
+ MigrationStatus["FailImage"] = "FailImage";
761
+ MigrationStatus["FailPhoto"] = "FailPhoto";
762
+ MigrationStatus["FailStory"] = "FailStory";
763
+ MigrationStatus["FailGallery"] = "FailGallery";
764
+ MigrationStatus["FailAuthor"] = "FailAuthor";
765
+ MigrationStatus["FailTag"] = "FailTag";
766
+ MigrationStatus["ValidationFailed"] = "ValidationFailed";
767
+ })(MigrationStatus || (MigrationStatus = {}));
768
+ var SummarySortBy;
769
+ (function (SummarySortBy) {
770
+ SummarySortBy["CreateDate"] = "createDate";
771
+ SummarySortBy["UpdateDate"] = "updateDate";
772
+ SummarySortBy["Id"] = "id";
773
+ })(SummarySortBy || (SummarySortBy = {}));
774
+ var SummarySortOrder;
775
+ (function (SummarySortOrder) {
776
+ SummarySortOrder["ASC"] = "ASC";
777
+ SummarySortOrder["DESC"] = "DESC";
778
+ })(SummarySortOrder || (SummarySortOrder = {}));
779
+
780
+ var index$3 = /*#__PURE__*/Object.freeze({
781
+ __proto__: null,
782
+ ANS: ansTypes,
783
+ get ANSType () { return ANSType; },
784
+ get MigrationStatus () { return MigrationStatus; },
785
+ get SummarySortBy () { return SummarySortBy; },
786
+ get SummarySortOrder () { return SummarySortOrder; },
787
+ TypeUtils: utils
788
+ });
789
+
790
+ const reference = (ref) => {
791
+ return {
792
+ _id: ref.id,
793
+ type: 'reference',
794
+ referent: {
795
+ ...ref,
796
+ },
797
+ };
798
+ };
799
+
800
+ var ANS = /*#__PURE__*/Object.freeze({
801
+ __proto__: null,
802
+ reference: reference
803
+ });
804
+
805
+ const ContentElement = {
806
+ divider: () => {
807
+ return {
808
+ type: 'divider',
809
+ };
810
+ },
811
+ text: (content, alignment = 'left') => {
812
+ return {
813
+ type: 'text',
814
+ content,
815
+ alignment: alignment || undefined,
816
+ };
817
+ },
818
+ quote: (items, citation = '', subtype = 'pullquote') => {
819
+ return {
820
+ type: 'quote',
821
+ subtype,
822
+ citation: {
823
+ type: 'text',
824
+ content: citation,
825
+ },
826
+ content_elements: items,
827
+ };
828
+ },
829
+ interstitial_link: (url, content) => {
830
+ return {
831
+ type: 'interstitial_link',
832
+ url,
833
+ content,
834
+ };
835
+ },
836
+ header: (content, level) => {
837
+ return {
838
+ type: 'header',
839
+ content,
840
+ level,
841
+ };
842
+ },
843
+ raw_html: (content) => {
844
+ return {
845
+ type: 'raw_html',
846
+ content,
847
+ };
848
+ },
849
+ gallery: (id) => {
850
+ return {
851
+ type: 'reference',
852
+ referent: {
853
+ type: 'gallery',
854
+ id,
855
+ },
856
+ };
857
+ },
858
+ list: (type, items) => {
859
+ return {
860
+ type: 'list',
861
+ list_type: type,
862
+ items,
863
+ };
864
+ },
865
+ link_list: (title, links) => {
866
+ return {
867
+ type: 'link_list',
868
+ title,
869
+ items: links.map(({ content, url }) => {
870
+ return {
871
+ type: 'interstitial_link',
872
+ content,
873
+ url,
874
+ };
875
+ }),
876
+ };
877
+ },
878
+ image: (id, properties) => {
879
+ return {
880
+ referent: {
881
+ id,
882
+ type: 'image',
883
+ referent_properties: {
884
+ _id: id,
885
+ type: 'image',
886
+ ...properties,
887
+ },
888
+ },
889
+ type: 'reference',
890
+ };
891
+ },
892
+ jwPlayer: (id) => {
893
+ return {
894
+ embed: {
895
+ config: {},
896
+ id,
897
+ url: 'https://cdn.jwplayer.com/players',
898
+ },
899
+ subtype: 'jw_player',
900
+ type: 'custom_embed',
901
+ };
902
+ },
903
+ twitter: (id, provider = 'https://publish.twitter.com/oembed?url=') => {
904
+ return {
905
+ referent: {
906
+ id,
907
+ provider,
908
+ service: 'oembed',
909
+ type: 'twitter',
910
+ },
911
+ type: 'reference',
912
+ };
913
+ },
914
+ youtube: (id, provider = 'https://www.youtube.com/oembed?url=') => {
915
+ return {
916
+ referent: {
917
+ id,
918
+ provider,
919
+ service: 'oembed',
920
+ type: 'youtube',
921
+ },
922
+ type: 'reference',
923
+ };
924
+ },
925
+ facebook_video: (id, provider = 'https://www.facebook.com/plugins/post/oembed.json/?url=') => {
926
+ return {
927
+ referent: {
928
+ id,
929
+ provider,
930
+ service: 'oembed',
931
+ type: 'facebook-video',
932
+ },
933
+ type: 'reference',
934
+ };
935
+ },
936
+ facebook_post: (id, provider = 'https://www.facebook.com/plugins/post/oembed.json/?url=') => {
937
+ return {
938
+ referent: {
939
+ id,
940
+ provider,
941
+ service: 'oembed',
942
+ type: 'facebook-post',
943
+ },
944
+ type: 'reference',
945
+ };
946
+ },
947
+ soundcloud: (id, provider = 'https://soundcloud.com/oembed.json/?url=') => {
948
+ return {
949
+ referent: {
950
+ id,
951
+ provider,
952
+ service: 'oembed',
953
+ type: 'soundcloud',
954
+ },
955
+ type: 'reference',
956
+ };
957
+ },
958
+ vimeo: (id, provider = 'https://vimeo.com/api/oembed.json?url=') => {
959
+ return {
960
+ referent: {
961
+ id,
962
+ provider,
963
+ service: 'oembed',
964
+ type: 'vimeo',
965
+ },
966
+ type: 'reference',
967
+ };
968
+ },
969
+ instagram: (id, provider = 'https://api.instagram.com/oembed?url=') => {
970
+ return {
971
+ referent: {
972
+ id,
973
+ provider,
974
+ service: 'oembed',
975
+ type: 'instagram',
976
+ },
977
+ type: 'reference',
978
+ };
979
+ },
980
+ dailymotion: (id, provider = 'https://www.dailymotion.com/services/oembed?url=') => {
981
+ return {
982
+ referent: {
983
+ id,
984
+ provider,
985
+ service: 'oembed',
986
+ type: 'dailymotion',
987
+ },
988
+ type: 'reference',
989
+ };
990
+ },
991
+ tiktok: (id, provider = 'https://www.tiktok.com/oembed?url=') => {
992
+ return {
993
+ referent: {
994
+ id,
995
+ provider,
996
+ service: 'oembed',
997
+ type: 'tiktok',
998
+ },
999
+ type: 'reference',
1000
+ };
1001
+ },
1002
+ issuu: (id, provider = 'https://issuu.com/oembed_wp?url=') => {
1003
+ return {
1004
+ referent: {
1005
+ id,
1006
+ provider,
1007
+ service: 'oembed',
1008
+ type: 'issuu',
1009
+ },
1010
+ type: 'reference',
1011
+ };
1012
+ },
1013
+ kickstarter: (id, provider = 'https://www.kickstarter.com/services/oembed?url=') => {
1014
+ return {
1015
+ referent: {
1016
+ id,
1017
+ provider,
1018
+ service: 'oembed',
1019
+ type: 'kickstarter',
1020
+ },
1021
+ type: 'reference',
1022
+ };
1023
+ },
1024
+ polldaddy: (id, provider = 'https://polldaddy.com/oembed/?url=') => {
1025
+ return {
1026
+ referent: {
1027
+ id,
1028
+ provider,
1029
+ service: 'oembed',
1030
+ type: 'polldaddy',
1031
+ },
1032
+ type: 'reference',
1033
+ };
1034
+ },
1035
+ };
1036
+
1037
+ const socialRegExps = {
1038
+ instagram: /(?:https?:\/\/)?(?:www.)?instagram.com\/?([a-zA-Z0-9\.\_\-]+)?\/([p]+)?([reel]+)?([tv]+)?([stories]+)?\/([a-zA-Z0-9\-\_\.]+)\/?([0-9]+)?/,
1039
+ twitter: /https:\/\/(?:www\.)?twitter\.com\/[^\/]+\/status(?:es)?\/(\d+)/,
1040
+ tiktok: /https:\/\/(?:m|www|vm)?\.?tiktok\.com\/((?:.*\b(?:(?:usr|v|embed|user|video)\/|\?shareId=|\&item_id=)(\d+))|\w+)/,
1041
+ facebookPost: /https:\/\/www\.facebook\.com\/(photo(\.php|s)|permalink\.php|media|questions|notes|[^\/]+\/(activity|posts))[\/?].*$/,
1042
+ facebookVideo: /https:\/\/www\.facebook\.com\/([^\/?].+\/)?video(s|\.php)[\/?].*/,
1043
+ };
1044
+ function match(url, regex) {
1045
+ return url.match(regex)?.[0];
1046
+ }
1047
+ function youtubeURLParser(url = '') {
1048
+ const regExp = /(?:youtube(?:-nocookie)?\.com\/(?:[^\/\n\s]+\/\S+\/|(?:v|e(?:mbed)?)\/|\S*?[?&]vi?=)|youtu\.be\/)([a-zA-Z0-9_-]{11})/;
1049
+ const id = url?.match(regExp)?.[1];
1050
+ if (id) {
1051
+ return `https://youtu.be/${id}`;
1052
+ }
1053
+ const paylistMatch = url?.match(/[?&]list=([^#&?]+)/);
1054
+ if (paylistMatch?.[1]) {
1055
+ return `https://www.youtube.com/embed/videoseries?list=${paylistMatch?.[1]}`;
1056
+ }
1057
+ return undefined;
1058
+ }
1059
+ function twitterURLParser(url) {
1060
+ return match(url, socialRegExps.twitter);
1061
+ }
1062
+ function instagramURLParser(url) {
1063
+ return match(url, socialRegExps.instagram);
1064
+ }
1065
+ function tiktokURLParser(url) {
1066
+ return match(url, socialRegExps.tiktok);
1067
+ }
1068
+ function facebookVideoURLParser(url) {
1069
+ return match(url, socialRegExps.facebookVideo);
1070
+ }
1071
+ function facebookPostURLParser(url) {
1072
+ return match(url, socialRegExps.facebookPost);
1073
+ }
1074
+ function createSocial(url = '') {
1075
+ const embeds = [];
1076
+ const instagram = instagramURLParser(url);
1077
+ if (instagram) {
1078
+ embeds.push(ContentElement.instagram(instagram));
1079
+ }
1080
+ const twitter = twitterURLParser(url);
1081
+ if (twitter) {
1082
+ embeds.push(ContentElement.twitter(twitter));
1083
+ }
1084
+ const tiktok = tiktokURLParser(url);
1085
+ if (tiktok) {
1086
+ embeds.push(ContentElement.tiktok(tiktok));
1087
+ }
1088
+ const youtube = youtubeURLParser(url);
1089
+ if (youtube) {
1090
+ embeds.push(ContentElement.youtube(youtube));
1091
+ }
1092
+ const facebookPost = facebookPostURLParser(url);
1093
+ if (facebookPost) {
1094
+ embeds.push(ContentElement.facebook_post(facebookPost));
1095
+ }
1096
+ const facebookVideo = facebookVideoURLParser(url);
1097
+ if (facebookVideo) {
1098
+ embeds.push(ContentElement.facebook_video(facebookVideo));
1099
+ }
1100
+ return embeds;
1101
+ }
1102
+ const randomId = () => `${new Date().toISOString()}-${Math.random()}`;
1103
+
1104
+ var ContentElements = /*#__PURE__*/Object.freeze({
1105
+ __proto__: null,
1106
+ createSocial: createSocial,
1107
+ facebookPostURLParser: facebookPostURLParser,
1108
+ facebookVideoURLParser: facebookVideoURLParser,
1109
+ instagramURLParser: instagramURLParser,
1110
+ randomId: randomId,
1111
+ tiktokURLParser: tiktokURLParser,
1112
+ twitterURLParser: twitterURLParser,
1113
+ youtubeURLParser: youtubeURLParser
17
1114
  });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
1115
+
1116
+ const generateArcId = (identifier, orgHostname) => {
1117
+ const namespace = v5(orgHostname, v5.DNS);
1118
+ const buffer = v5(identifier, namespace, Buffer.alloc(16));
1119
+ return encode(buffer, 'RFC4648', { padding: false });
1120
+ };
1121
+ /**
1122
+ * Utility class for generating Arc IDs and source IDs
1123
+ *
1124
+ * @example
1125
+ * ```ts
1126
+ * const generator = new IdGenerator(['my-org']);
1127
+ * const arcId = generator.getArcId('123'); // Generates a unique for 'my-org' Arc ID
1128
+ * const sourceId = generator.getSourceId('123', ['my-site']); // Generates 'my-site-123'
1129
+ * ```
1130
+ */
1131
+ class IdGenerator {
1132
+ constructor(namespaces) {
1133
+ if (!namespaces.length) {
1134
+ throw new Error('At least 1 namespace is required');
1135
+ }
1136
+ this.namespace = namespaces.join('-');
1137
+ }
1138
+ getArcId(id) {
1139
+ return generateArcId(id.toString(), this.namespace);
1140
+ }
1141
+ getSourceId(id, prefixes = []) {
1142
+ return [...prefixes, id].join('-');
1143
+ }
1144
+ }
1145
+
1146
+ var Id = /*#__PURE__*/Object.freeze({
1147
+ __proto__: null,
1148
+ IdGenerator: IdGenerator,
1149
+ generateArcId: generateArcId
1150
+ });
1151
+
1152
+ const buildTree = (items) => {
1153
+ const tree = [
1154
+ {
1155
+ id: '/',
1156
+ children: [],
1157
+ meta: new Proxy({}, {
1158
+ get: () => {
1159
+ throw new Error('Root node meta is not accessible');
1160
+ },
1161
+ }),
1162
+ parent: null,
1163
+ },
1164
+ ];
1165
+ // Track nodes at each level to maintain parent-child relationships
1166
+ // stores last node at each level
1167
+ const currLevelNodes = {
1168
+ 0: tree[0],
26
1169
  };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
1170
+ for (const item of items) {
1171
+ const node = {
1172
+ id: item.id,
1173
+ parent: null,
1174
+ children: [],
1175
+ meta: item,
1176
+ };
1177
+ // Determine the level of this node
1178
+ const levelKey = Object.keys(item).find((key) => key.startsWith('N') && item[key]);
1179
+ const level = Number(levelKey?.replace('N', '')) || 0;
1180
+ if (!level) {
1181
+ throw new Error(`Invalid level for section ${item.id}`);
1182
+ }
1183
+ // This is a child node - attach to its parent
1184
+ const parentLevel = level - 1;
1185
+ const parentNode = currLevelNodes[parentLevel];
1186
+ if (parentNode) {
1187
+ node.parent = parentNode;
1188
+ parentNode.children.push(node);
1189
+ }
1190
+ else {
1191
+ throw new Error(`Parent node not found for section ${item.id}`);
1192
+ }
1193
+ // Set this as the current node for its level
1194
+ currLevelNodes[level] = node;
1195
+ }
1196
+ // return root nodes children
1197
+ return tree[0].children;
1198
+ };
1199
+ const flattenTree = (tree) => {
1200
+ const flatten = [];
1201
+ const traverse = (node) => {
1202
+ flatten.push(node);
1203
+ for (const child of node.children) {
1204
+ traverse(child);
1205
+ }
33
1206
  };
34
- })();
35
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
36
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.ContentElements = exports.AnsMapper = exports.WsClient = exports.ArcError = exports.ArcUtils = exports.ArcAPI = exports.ArcTypes = void 0;
40
- exports.ArcTypes = __importStar(require("./types"));
41
- __exportStar(require("./api/identity/types"), exports);
42
- __exportStar(require("./api/draft/types"), exports);
43
- __exportStar(require("./api/site/types"), exports);
44
- __exportStar(require("./api/ifx/types"), exports);
45
- __exportStar(require("./api/redirect/types"), exports);
46
- __exportStar(require("./api/migration-center/types"), exports);
47
- __exportStar(require("./api/sales/types"), exports);
48
- __exportStar(require("./api/websked/types"), exports);
49
- __exportStar(require("./api/content/types"), exports);
50
- __exportStar(require("./api/photo-center/types"), exports);
51
- __exportStar(require("./api/global-settings/types"), exports);
52
- __exportStar(require("./api/tags/types"), exports);
53
- __exportStar(require("./api/content-ops/types"), exports);
54
- var api_1 = require("./api");
55
- Object.defineProperty(exports, "ArcAPI", { enumerable: true, get: function () { return api_1.ArcAPI; } });
56
- var arc_1 = require("./utils/arc");
57
- Object.defineProperty(exports, "ArcUtils", { enumerable: true, get: function () { return arc_1.ArcUtils; } });
58
- var error_1 = require("./api/error");
59
- Object.defineProperty(exports, "ArcError", { enumerable: true, get: function () { return error_1.ArcError; } });
60
- var ws_client_1 = require("./api/ws.client");
61
- Object.defineProperty(exports, "WsClient", { enumerable: true, get: function () { return ws_client_1.WsClient; } });
62
- exports.AnsMapper = __importStar(require("./mapper"));
63
- exports.ContentElements = __importStar(require("./content-elements"));
64
- //# sourceMappingURL=index.js.map
1207
+ // traverse all root nodes and their children
1208
+ for (const node of tree) {
1209
+ traverse(node);
1210
+ }
1211
+ return flatten;
1212
+ };
1213
+ const buildAndFlattenTree = (items) => flattenTree(buildTree(items));
1214
+ const groupByWebsites = (sections) => {
1215
+ return sections.reduce((acc, section) => {
1216
+ const website = section._website;
1217
+ if (!acc[website])
1218
+ acc[website] = [];
1219
+ acc[website].push(section);
1220
+ return acc;
1221
+ }, {});
1222
+ };
1223
+ const references = (sections) => {
1224
+ return sections.map((s) => reference({
1225
+ id: s._id,
1226
+ website: s._website,
1227
+ type: 'section',
1228
+ }));
1229
+ };
1230
+ const isReference = (section) => {
1231
+ return section?.type === 'reference' && section?.referent?.type === 'section';
1232
+ };
1233
+ const removeDuplicates = (sections) => {
1234
+ const map = new Map();
1235
+ sections.forEach((s) => {
1236
+ if (isReference(s)) {
1237
+ map.set(`${s.referent.id}${s.referent.website}`, s);
1238
+ }
1239
+ else {
1240
+ map.set(`${s._id}${s._website}`, s);
1241
+ }
1242
+ });
1243
+ return [...map.values()];
1244
+ };
1245
+ class SectionsRepository {
1246
+ constructor(arc) {
1247
+ this.arc = arc;
1248
+ this.sectionsByWebsite = {};
1249
+ this.websitesAreLoaded = false;
1250
+ }
1251
+ async put(ans) {
1252
+ await this.arc.Site.putSection(ans);
1253
+ const created = await this.arc.Site.getSection(ans._id, ans.website);
1254
+ this.save(created);
1255
+ }
1256
+ async loadWebsite(website) {
1257
+ const sections = [];
1258
+ let next = true;
1259
+ let offset = 0;
1260
+ while (next) {
1261
+ const migrated = await this.arc.Site.getSections({ website, offset }).catch((_) => {
1262
+ return { q_results: [] };
1263
+ });
1264
+ if (migrated.q_results.length) {
1265
+ sections.push(...migrated.q_results);
1266
+ offset += migrated.q_results.length;
1267
+ }
1268
+ else {
1269
+ next = false;
1270
+ }
1271
+ }
1272
+ return sections;
1273
+ }
1274
+ async loadWebsites(websites) {
1275
+ for (const website of websites) {
1276
+ this.sectionsByWebsite[website] = await this.loadWebsite(website);
1277
+ }
1278
+ this.websitesAreLoaded = true;
1279
+ }
1280
+ save(section) {
1281
+ const website = section._website;
1282
+ assert.ok(website, 'Section must have a website');
1283
+ this.sectionsByWebsite[website] = this.sectionsByWebsite[website] || [];
1284
+ if (!this.sectionsByWebsite[website].find((s) => s._id === section._id)) {
1285
+ this.sectionsByWebsite[website].push(section);
1286
+ }
1287
+ }
1288
+ getById(id, website) {
1289
+ this.ensureWebsitesLoaded();
1290
+ const section = this.sectionsByWebsite[website]?.find((s) => s._id === id);
1291
+ return section;
1292
+ }
1293
+ getByWebsite(website) {
1294
+ this.ensureWebsitesLoaded();
1295
+ return this.sectionsByWebsite[website];
1296
+ }
1297
+ getParentSections(section) {
1298
+ this.ensureWebsitesLoaded();
1299
+ const parents = [];
1300
+ let current = section;
1301
+ while (current.parent?.default && current.parent.default !== '/') {
1302
+ const parent = this.getById(current.parent.default, section._website);
1303
+ if (!parent)
1304
+ break;
1305
+ parents.push(parent);
1306
+ current = parent;
1307
+ }
1308
+ return parents;
1309
+ }
1310
+ ensureWebsitesLoaded() {
1311
+ assert.ok(this.websitesAreLoaded, 'call .loadWebsites() first');
1312
+ }
1313
+ }
1314
+
1315
+ var Section = /*#__PURE__*/Object.freeze({
1316
+ __proto__: null,
1317
+ SectionsRepository: SectionsRepository,
1318
+ buildAndFlattenTree: buildAndFlattenTree,
1319
+ buildTree: buildTree,
1320
+ flattenTree: flattenTree,
1321
+ groupByWebsites: groupByWebsites,
1322
+ isReference: isReference,
1323
+ references: references,
1324
+ removeDuplicates: removeDuplicates
1325
+ });
1326
+
1327
+ const ArcUtils = {
1328
+ Id,
1329
+ ANS,
1330
+ ContentElements,
1331
+ Section,
1332
+ };
1333
+
1334
+ /**
1335
+ * Base class for all arc entities, it provides common methods and properties
1336
+ * If you want to create a new entity subtype you should extend this class
1337
+ *
1338
+ * Use case: You want to migrate stories from BBC
1339
+ * You define `class BBCStory extends ArcDocument<ANS.AStory>` and implement all abstract methods
1340
+ * Then you can override the specific methods to enrich the story with the data from BBC
1341
+ *
1342
+ * To migrate it call .migrate() method
1343
+ */
1344
+ class Document {
1345
+ constructor() {
1346
+ this.ans = null;
1347
+ this.circulations = [];
1348
+ }
1349
+ async init() {
1350
+ // fetch necessary data and validate it here
1351
+ }
1352
+ async prepare() {
1353
+ await this.init();
1354
+ const payload = await this.payload();
1355
+ const params = await this.params();
1356
+ return { payload, params };
1357
+ }
1358
+ async payload() {
1359
+ this.ans = await this.getAns();
1360
+ this.circulations = await this.getCirculations();
1361
+ return {
1362
+ sourceId: await this.sourceId(),
1363
+ sourceType: await this.sourceType(),
1364
+ ANS: this.ans,
1365
+ circulations: this.circulations,
1366
+ arcAdditionalProperties: this.additionalProperties(),
1367
+ };
1368
+ }
1369
+ async params() {
1370
+ if (!this.websiteId()) {
1371
+ throw new Error('Website is not initialized! get params() should be called after payload()!');
1372
+ }
1373
+ return {
1374
+ website: await this.websiteId(),
1375
+ groupId: await this.groupId(),
1376
+ priority: this.priority(),
1377
+ };
1378
+ }
1379
+ additionalProperties() {
1380
+ return {
1381
+ story: {
1382
+ publish: false,
1383
+ },
1384
+ };
1385
+ }
1386
+ priority() {
1387
+ return 'historical';
1388
+ }
1389
+ getDistributor() {
1390
+ return;
1391
+ }
1392
+ getLanguage() {
1393
+ return 'en-GB';
1394
+ }
1395
+ getComments() {
1396
+ return;
1397
+ }
1398
+ async getSource() {
1399
+ return {
1400
+ name: 'code-store',
1401
+ system: 'code-store',
1402
+ source_id: await this.sourceId(),
1403
+ };
1404
+ }
1405
+ getSubheadlines() {
1406
+ return {
1407
+ basic: '',
1408
+ };
1409
+ }
1410
+ getDescription() {
1411
+ return this.getSubheadlines();
1412
+ }
1413
+ formatDate(date) {
1414
+ if (!date)
1415
+ return;
1416
+ return date.toISOString();
1417
+ }
1418
+ getDisplayDate() {
1419
+ return new Date();
1420
+ }
1421
+ async getContentElements() {
1422
+ return [];
1423
+ }
1424
+ getPublicationDate() {
1425
+ return new Date();
1426
+ }
1427
+ getHeadlines() {
1428
+ return {
1429
+ basic: '',
1430
+ };
1431
+ }
1432
+ getTags() {
1433
+ return;
1434
+ }
1435
+ getSubtype() {
1436
+ return;
1437
+ }
1438
+ getLabel() {
1439
+ return;
1440
+ }
1441
+ getRelatedContent() {
1442
+ return;
1443
+ }
1444
+ async getPromoItems() {
1445
+ return;
1446
+ }
1447
+ getWebskedStatusCode() {
1448
+ return;
1449
+ }
1450
+ getCreditsBy() {
1451
+ return [];
1452
+ }
1453
+ getCirculations() {
1454
+ return [];
1455
+ }
1456
+ getEditorNote() {
1457
+ return;
1458
+ }
1459
+ getContentRestrictions() {
1460
+ return;
1461
+ }
1462
+ getOwnerInformation() {
1463
+ return;
1464
+ }
1465
+ getSyndication() {
1466
+ return;
1467
+ }
1468
+ getSchedulingInformation() {
1469
+ return;
1470
+ }
1471
+ getTaxonomy() {
1472
+ return;
1473
+ }
1474
+ }
1475
+
1476
+ /**
1477
+ * Base class for all arc stories, it provides common methods and properties
1478
+ * If you want to create a new story subtype you should extend this class
1479
+ *
1480
+ * Use case: You want to migrate stories from BBC
1481
+ * You define `class BBCStory extends ArcStory` and implement all abstract methods
1482
+ * Then you need to override the specific methods to enrich the story with the data from BBC
1483
+ *
1484
+ * For example:
1485
+ * To add tag to BBC stories you need to override
1486
+ * protected getTags(): MaybePromise<ArcTypes.Story.Tag[]> {
1487
+ * return [{
1488
+ * slug: 'bbc',
1489
+ * text: 'bbc',
1490
+ * }];
1491
+ * }
1492
+ */
1493
+ class Story extends Document {
1494
+ type() {
1495
+ return 'story';
1496
+ }
1497
+ async getAns() {
1498
+ const id = await this.arcId();
1499
+ const version = this.version();
1500
+ const type = this.type();
1501
+ const publicationDate = await this.getPublicationDate();
1502
+ const displayDate = await this.getDisplayDate();
1503
+ const headlines = this.getHeadlines();
1504
+ const subheadlines = this.getSubheadlines();
1505
+ const description = this.getDescription();
1506
+ const language = this.getLanguage();
1507
+ const tags = await this.getTags();
1508
+ const subtype = await this.getSubtype();
1509
+ const label = await this.getLabel();
1510
+ const by = await this.getCreditsBy();
1511
+ const relatedContent = await this.getRelatedContent();
1512
+ const editorNote = await this.getEditorNote();
1513
+ const distributor = await this.getDistributor();
1514
+ const promoItems = await this.getPromoItems();
1515
+ const contentElements = await this.getContentElements();
1516
+ const webskedStatusCode = await this.getWebskedStatusCode();
1517
+ const websiteId = await this.websiteId();
1518
+ const source = await this.getSource();
1519
+ const comments = await this.getComments();
1520
+ const legacyUrl = await this.legacyUrl();
1521
+ const owner = await this.getOwnerInformation();
1522
+ const syndication = await this.getSyndication();
1523
+ const contentRestrictions = await this.getContentRestrictions();
1524
+ const planning = await this.getSchedulingInformation();
1525
+ const taxonomy = await this.getTaxonomy();
1526
+ const additionalMetaProperties = await this.getMigrationMetaProperties();
1527
+ return {
1528
+ type,
1529
+ _id: id,
1530
+ version,
1531
+ website: websiteId,
1532
+ canonical_website: websiteId,
1533
+ language,
1534
+ subtype,
1535
+ label,
1536
+ editor_note: editorNote,
1537
+ credits: {
1538
+ by,
1539
+ },
1540
+ headlines,
1541
+ subheadlines,
1542
+ description,
1543
+ distributor,
1544
+ planning,
1545
+ promo_items: promoItems,
1546
+ related_content: relatedContent,
1547
+ content_restrictions: contentRestrictions,
1548
+ created_date: this.formatDate(new Date()),
1549
+ first_publish_date: this.formatDate(publicationDate),
1550
+ publish_date: this.formatDate(publicationDate),
1551
+ display_date: this.formatDate(displayDate),
1552
+ source,
1553
+ comments,
1554
+ owner,
1555
+ syndication,
1556
+ taxonomy: {
1557
+ ...taxonomy,
1558
+ tags,
1559
+ },
1560
+ workflow: {
1561
+ status_code: webskedStatusCode,
1562
+ },
1563
+ content_elements: contentElements,
1564
+ additional_properties: {
1565
+ url: legacyUrl,
1566
+ ...additionalMetaProperties,
1567
+ },
1568
+ };
1569
+ }
1570
+ async getMigrationMetaProperties() {
1571
+ return {
1572
+ // used in dashboard for migration
1573
+ migration_source_id: await this.sourceId(),
1574
+ migration_source_type: await this.sourceType(),
1575
+ // used in dashboard to show the original url
1576
+ migration_url: await this.legacyUrl(),
1577
+ migration_group_id: await this.groupId(),
1578
+ };
1579
+ }
1580
+ }
1581
+
1582
+ var index$2 = /*#__PURE__*/Object.freeze({
1583
+ __proto__: null,
1584
+ Document: Document,
1585
+ Story: Story
1586
+ });
1587
+
1588
+ const BLOCK_ELEMENT_TAGS = [
1589
+ 'ADDRESS',
1590
+ 'ARTICLE',
1591
+ 'ASIDE',
1592
+ 'BLOCKQUOTE',
1593
+ 'DETAILS',
1594
+ 'DIV',
1595
+ 'DL',
1596
+ 'FIELDSET',
1597
+ 'FIGCAPTION',
1598
+ 'FIGURE',
1599
+ 'FOOTER',
1600
+ 'FORM',
1601
+ 'H1',
1602
+ 'H2',
1603
+ 'H3',
1604
+ 'H4',
1605
+ 'H5',
1606
+ 'H6',
1607
+ 'HEADER',
1608
+ 'HR',
1609
+ 'LINE',
1610
+ 'MAIN',
1611
+ 'MENU',
1612
+ 'NAV',
1613
+ 'OL',
1614
+ 'P',
1615
+ 'PARAGRAPH',
1616
+ 'PRE',
1617
+ 'SECTION',
1618
+ 'TABLE',
1619
+ 'UL',
1620
+ 'LI',
1621
+ 'BODY',
1622
+ 'HTML',
1623
+ ];
1624
+
1625
+ var html_constants = /*#__PURE__*/Object.freeze({
1626
+ __proto__: null,
1627
+ BLOCK_ELEMENT_TAGS: BLOCK_ELEMENT_TAGS
1628
+ });
1629
+
1630
+ const isTextNode = (node) => {
1631
+ return node instanceof TextNode;
1632
+ };
1633
+ const isHTMLElement = (node) => {
1634
+ return node instanceof HTMLElement;
1635
+ };
1636
+ const isCommentNode = (node) => {
1637
+ return node instanceof CommentNode;
1638
+ };
1639
+ const nodeTagIs = (node, name) => {
1640
+ return isHTMLElement(node) && node.tagName?.toLowerCase() === name.toLowerCase();
1641
+ };
1642
+ const nodeTagIn = (node, names) => {
1643
+ return isHTMLElement(node) && names.includes(node.tagName?.toLowerCase());
1644
+ };
1645
+ const isTextCE = (ce) => {
1646
+ return ce?.type === 'text';
1647
+ };
1648
+ const decodeHTMLEntities = (str) => decode(str);
1649
+ const htmlToText = (html, parseOptions) => {
1650
+ if (!html)
1651
+ return '';
1652
+ const doc = parse(html, parseOptions);
1653
+ return decodeHTMLEntities(doc.innerText);
1654
+ };
1655
+ const getHTMLElementAttribute = (e, key) => {
1656
+ const value = e.getAttribute(key);
1657
+ if (value)
1658
+ return value;
1659
+ return new URLSearchParams(e.rawAttrs.replaceAll(' ', '&')).get(key);
1660
+ };
1661
+
1662
+ var html_utils = /*#__PURE__*/Object.freeze({
1663
+ __proto__: null,
1664
+ decodeHTMLEntities: decodeHTMLEntities,
1665
+ getHTMLElementAttribute: getHTMLElementAttribute,
1666
+ htmlToText: htmlToText,
1667
+ isCommentNode: isCommentNode,
1668
+ isHTMLElement: isHTMLElement,
1669
+ isTextCE: isTextCE,
1670
+ isTextNode: isTextNode,
1671
+ nodeTagIn: nodeTagIn,
1672
+ nodeTagIs: nodeTagIs
1673
+ });
1674
+
1675
+ /**
1676
+ * HTMLProcessor is responsible for parsing HTML content into structured content elements.
1677
+ * It provides a flexible way to handle different HTML nodes and wrap text content.
1678
+ *
1679
+ * The processor can be extended with custom handlers for specific node types and
1680
+ * wrappers for text content.
1681
+ *
1682
+ * @example
1683
+ * ```ts
1684
+ * // Create and initialize processor
1685
+ * const processor = new HTMLProcessor();
1686
+ * processor.init();
1687
+ *
1688
+ * // Parse HTML content
1689
+ * const html = '<div><p>Some text</p><img src="image.jpg"></div>';
1690
+ * const elements = await processor.parse(html);
1691
+ * ```
1692
+ *
1693
+ * The processor comes with built-in handlers for common HTML elements like links,
1694
+ * text formatting (i, u, strong), and block elements. Custom handlers can be added
1695
+ * using the `handle()` and `wrap()` methods.
1696
+ */
1697
+ class HTMLProcessor {
1698
+ constructor() {
1699
+ this.parallelProcessing = true;
1700
+ this.handlers = {
1701
+ node: new Map(),
1702
+ wrap: new Map(),
1703
+ };
1704
+ }
1705
+ init() {
1706
+ // wrappers are used to wrap the content of nested text nodes
1707
+ // in a specific way
1708
+ this.wrap('link', (node, text) => {
1709
+ if (nodeTagIn(node, ['a'])) {
1710
+ const attributes = ['href', 'target', 'rel']
1711
+ .map((attr) => [attr, getHTMLElementAttribute(node, attr)])
1712
+ .filter(([_, value]) => value)
1713
+ .map(([key, value]) => `${key}="${value}"`)
1714
+ .join(' ');
1715
+ return {
1716
+ ...text,
1717
+ content: `<a ${attributes}>${text.content}</a>`,
1718
+ };
1719
+ }
1720
+ });
1721
+ this.wrap('i', (node, text) => {
1722
+ if (nodeTagIn(node, ['i'])) {
1723
+ return {
1724
+ ...text,
1725
+ content: `<i>${text.content}</i>`,
1726
+ };
1727
+ }
1728
+ });
1729
+ this.wrap('u', (node, text) => {
1730
+ if (nodeTagIn(node, ['u'])) {
1731
+ return {
1732
+ ...text,
1733
+ content: `<u>${text.content}</u>`,
1734
+ };
1735
+ }
1736
+ });
1737
+ this.wrap('sup/sub', (node, text) => {
1738
+ if (nodeTagIn(node, ['sup', 'sub'])) {
1739
+ return {
1740
+ ...text,
1741
+ content: `<mark class="${node.tagName.toLowerCase()}">${text.content}</mark>`,
1742
+ };
1743
+ }
1744
+ });
1745
+ this.wrap('strong', (node, text) => {
1746
+ if (nodeTagIn(node, ['strong', 'b'])) {
1747
+ return {
1748
+ ...text,
1749
+ content: `<b>${text.content}</b>`,
1750
+ };
1751
+ }
1752
+ });
1753
+ this.wrap('center', (node, text) => {
1754
+ if (nodeTagIn(node, ['center'])) {
1755
+ return {
1756
+ ...text,
1757
+ alignment: 'center',
1758
+ };
1759
+ }
1760
+ });
1761
+ this.wrap('aligned-paragraph', (node, text) => {
1762
+ if (nodeTagIn(node, ['p'])) {
1763
+ const styleAttribute = getHTMLElementAttribute(node, 'style') || '';
1764
+ if (!styleAttribute)
1765
+ return text;
1766
+ if (styleAttribute.includes('text-align: right;')) {
1767
+ return {
1768
+ ...text,
1769
+ alignment: 'right',
1770
+ };
1771
+ }
1772
+ if (styleAttribute.includes('text-align: left;')) {
1773
+ return {
1774
+ ...text,
1775
+ alignment: 'left',
1776
+ };
1777
+ }
1778
+ if (styleAttribute.includes('text-align: center;')) {
1779
+ return {
1780
+ ...text,
1781
+ alignment: 'center',
1782
+ };
1783
+ }
1784
+ return text;
1785
+ }
1786
+ });
1787
+ // handlers are used to handle specific nodes
1788
+ // and return a list of content elements
1789
+ this.handle('default', (node) => {
1790
+ const noTag = isHTMLElement(node) && !node.tagName;
1791
+ if (noTag ||
1792
+ nodeTagIn(node, [
1793
+ 'p',
1794
+ 'a',
1795
+ 'b',
1796
+ 'sup',
1797
+ 'sub',
1798
+ 'span',
1799
+ 'strong',
1800
+ 'em',
1801
+ 'i',
1802
+ 'u',
1803
+ 'section',
1804
+ 'main',
1805
+ 'div',
1806
+ 'li',
1807
+ 'center',
1808
+ ])) {
1809
+ return this.handleNested(node);
1810
+ }
1811
+ });
1812
+ this.handle('headers', (node) => {
1813
+ if (nodeTagIn(node, ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'])) {
1814
+ return this.createHeader(node);
1815
+ }
1816
+ });
1817
+ this.handle('text', (node) => {
1818
+ if (isTextNode(node)) {
1819
+ return this.createText(node);
1820
+ }
1821
+ });
1822
+ this.handle('comment', (node) => {
1823
+ if (isCommentNode(node)) {
1824
+ return this.handleComment(node);
1825
+ }
1826
+ });
1827
+ this.handle('list', async (node) => {
1828
+ if (nodeTagIn(node, ['ul', 'ol'])) {
1829
+ const listType = node.tagName === 'UL' ? 'unordered' : 'ordered';
1830
+ return this.createList(node, listType);
1831
+ }
1832
+ });
1833
+ this.handle('table', (node) => {
1834
+ if (nodeTagIs(node, 'table')) {
1835
+ return this.handleTable(node);
1836
+ }
1837
+ });
1838
+ this.handle('iframe', (node) => {
1839
+ if (nodeTagIs(node, 'iframe')) {
1840
+ return this.handleIframe(node);
1841
+ }
1842
+ });
1843
+ this.handle('img', (node) => {
1844
+ if (nodeTagIs(node, 'img')) {
1845
+ return this.handleImage(node);
1846
+ }
1847
+ });
1848
+ this.handle('br', (node) => {
1849
+ if (nodeTagIs(node, 'br')) {
1850
+ return this.handleBreak(node);
1851
+ }
1852
+ });
1853
+ }
1854
+ handle(name, handler) {
1855
+ if (this.handlers.node.has(name)) {
1856
+ this.warn({ name }, `${name} node handler already set`);
1857
+ }
1858
+ this.handlers.node.set(name, handler);
1859
+ }
1860
+ wrap(name, handler) {
1861
+ if (this.handlers.wrap.has(name)) {
1862
+ this.warn({ name }, `${name} wrap handler already set`);
1863
+ }
1864
+ this.handlers.wrap.set(name, handler);
1865
+ }
1866
+ async parse(html) {
1867
+ const doc = parse(html, { comment: true });
1868
+ doc.removeWhitespace();
1869
+ const elements = await this.process(doc);
1870
+ const filtered = elements?.filter((e) => e.type !== 'divider');
1871
+ return filtered || [];
1872
+ }
1873
+ addTextAdditionalProperties(c, parent) {
1874
+ const additionalProperties = c.additional_properties || {};
1875
+ const parentNodeIsBlockElement = this.isBlockElement(parent);
1876
+ c.additional_properties = {
1877
+ ...c.additional_properties,
1878
+ isBlockElement: additionalProperties.isBlockElement || parentNodeIsBlockElement,
1879
+ };
1880
+ return c;
1881
+ }
1882
+ /**
1883
+ * Wraps text content elements with additional properties and handlers.
1884
+ * This method iterates through an array of content elements and applies
1885
+ * wrappers to text elements.
1886
+ *
1887
+ * @param node - The HTML node containing the text elements
1888
+ **/
1889
+ wrapChildrenTextNodes(node, elements) {
1890
+ const wrapped = [];
1891
+ const wrappers = [...this.handlers.wrap.values()];
1892
+ for (const c of elements) {
1893
+ if (!isTextCE(c)) {
1894
+ wrapped.push(c);
1895
+ continue;
1896
+ }
1897
+ this.addTextAdditionalProperties(c, node);
1898
+ const handled = wrappers.map((wrapper) => wrapper(node, c)).find(Boolean);
1899
+ wrapped.push(handled || c);
1900
+ }
1901
+ return wrapped;
1902
+ }
1903
+ /**
1904
+ * Handles nested nodes by processing their children and merging text elements.
1905
+ * This method recursively processes the children of a given HTML node and
1906
+ * returns a list of content elements.
1907
+ *
1908
+ * @param node - The HTML node to process
1909
+ **/
1910
+ async handleNested(node) {
1911
+ const children = await this.processChildNodes(node);
1912
+ const filtered = children.filter(Boolean).flat();
1913
+ const merged = this.mergeParagraphs(filtered);
1914
+ const wrapped = this.wrapChildrenTextNodes(node, merged);
1915
+ return wrapped;
1916
+ }
1917
+ async processChildNodes(node) {
1918
+ if (this.parallelProcessing) {
1919
+ return await Promise.all(node.childNodes.map((child) => this.process(child)));
1920
+ }
1921
+ const children = [];
1922
+ for (const child of node.childNodes) {
1923
+ children.push(await this.process(child));
1924
+ }
1925
+ return children;
1926
+ }
1927
+ /**
1928
+ * Processes a single HTML node and converts it into content elements.
1929
+ * This method iterates through registered node handlers and attempts to process the node.
1930
+ * If a handler successfully processes the node, it returns an array of content elements.
1931
+ *
1932
+ * @param node - The HTML node to process
1933
+ * @returns Promise resolving to an array of content elements, or undefined if node cannot be processed
1934
+ */
1935
+ async process(node) {
1936
+ let isKnownNode = false;
1937
+ const elements = [];
1938
+ for (const [name, handler] of this.handlers.node.entries()) {
1939
+ try {
1940
+ const result = await handler(node);
1941
+ if (result) {
1942
+ // if handler returns an array of elements, it means that the node was handled properly, even if there is no elements inside
1943
+ isKnownNode = true;
1944
+ elements.push(...result);
1945
+ break;
1946
+ }
1947
+ }
1948
+ catch (error) {
1949
+ this.warn({ node: node.toString(), error: error.toString(), name }, 'HandlerError');
1950
+ }
1951
+ }
1952
+ if (isKnownNode)
1953
+ return elements;
1954
+ this.warn({ node: node.toString() }, 'UnknownNodeError');
1955
+ }
1956
+ /**
1957
+ * Merges adjacent text content elements into a single paragraph.
1958
+ * This method iterates through an array of content elements and combines
1959
+ * adjacent text elements into a single paragraph.
1960
+ *
1961
+ * @param items - The array of content elements to merge
1962
+ **/
1963
+ mergeParagraphs(items) {
1964
+ const merged = [];
1965
+ let toMerge = [];
1966
+ const merge = () => {
1967
+ if (!toMerge.length)
1968
+ return;
1969
+ const paragraph = toMerge.reduce((acc, p) => {
1970
+ return {
1971
+ ...p,
1972
+ content: acc.content + p.content,
1973
+ };
1974
+ }, { type: 'text', content: '' });
1975
+ merged.push(paragraph);
1976
+ toMerge = [];
1977
+ };
1978
+ for (let i = 0; i < items.length; i++) {
1979
+ const item = items[i];
1980
+ const isBlockElement = item.additional_properties?.isBlockElement;
1981
+ if (isTextCE(item) && !isBlockElement) {
1982
+ toMerge.push(item);
1983
+ }
1984
+ else {
1985
+ merge();
1986
+ merged.push(item);
1987
+ }
1988
+ }
1989
+ merge();
1990
+ return merged;
1991
+ }
1992
+ handleComment(_) {
1993
+ return [];
1994
+ }
1995
+ async handleTable(node) {
1996
+ return [ContentElement.raw_html(node.toString())];
1997
+ }
1998
+ async handleIframe(node) {
1999
+ return [ContentElement.raw_html(node.toString())];
2000
+ }
2001
+ async handleImage(node) {
2002
+ return [ContentElement.raw_html(node.toString())];
2003
+ }
2004
+ async handleBreak(_) {
2005
+ return [ContentElement.divider()];
2006
+ }
2007
+ async createQuote(node) {
2008
+ const items = await this.handleNested(node);
2009
+ return [ContentElement.quote(items)];
2010
+ }
2011
+ async createText(node) {
2012
+ const text = ContentElement.text(node.text);
2013
+ return [text];
2014
+ }
2015
+ filterListItems(items) {
2016
+ return items.filter((i) => ['text', 'list'].includes(i.type));
2017
+ }
2018
+ async createList(node, type) {
2019
+ const items = await this.handleNested(node);
2020
+ return [ContentElement.list(type, this.filterListItems(items))];
2021
+ }
2022
+ async createHeader(node) {
2023
+ const level = +node.tagName.split('H')[1] || 3;
2024
+ return [ContentElement.header(node.innerText, level)];
2025
+ }
2026
+ isBlockElement(node) {
2027
+ if (!isHTMLElement(node))
2028
+ return false;
2029
+ const defaultBlockElements = new Set(BLOCK_ELEMENT_TAGS);
2030
+ return defaultBlockElements.has(node.tagName);
2031
+ }
2032
+ warn(metadata, message) {
2033
+ console.warn(metadata, message);
2034
+ }
2035
+ }
2036
+
2037
+ var index$1 = /*#__PURE__*/Object.freeze({
2038
+ __proto__: null,
2039
+ Constants: html_constants,
2040
+ HTMLProcessor: HTMLProcessor,
2041
+ Utils: html_utils
2042
+ });
2043
+
2044
+ var index = /*#__PURE__*/Object.freeze({
2045
+ __proto__: null,
2046
+ ContentElement: ContentElement,
2047
+ HTML: index$1
2048
+ });
2049
+
2050
+ export { index$2 as AnsMapper, ArcAPI, ArcError, index$3 as ArcTypes, ArcUtils, index as ContentElements, WsClient, ArcAPI as default };
2051
+ //# sourceMappingURL=index.js.map