UNPKG

7.32 kBPlain TextView Raw
1import * as fs from "fs";
2import * as request from "request";
3import * as retry from "retry";
4
5import { MagnoliaSourceOptions } from "./magnolia-source-options.interface";
6import { MagnoliaLoadingParams } from "./magnolia-loading-params.interface";
7
8export function fetchSitemap(
9 options: MagnoliaSourceOptions
10): Promise<string[]> {
11 return loadDataFromMagnolia<string[]>({
12 authHeader: options.magnolia.auth.header,
13 url: options.magnolia.url + options.magnolia.sitemapEndpoint,
14 errorMessage:
15 "Attempt to get the sitemap failed, will retry in some time...",
16 resolverHandler: body => body,
17 retryOptions: { forever: true }
18 });
19}
20
21export function fetchWorkspace(
22 workspace: string,
23 options: MagnoliaSourceOptions
24): Promise<any> {
25 return loadDataFromMagnolia<any>({
26 authHeader: options.magnolia.auth.header,
27 url: options.magnolia.url + "/.rest/delivery/" + workspace + "/v1",
28 errorMessage: `Attempt to get workspace ${workspace} failed, will retry in some time...`,
29 resolverHandler: body => body.results
30 });
31}
32
33export function fetchPages(options: MagnoliaSourceOptions): Promise<any> {
34 return loadDataFromMagnolia<any>({
35 authHeader: options.magnolia.auth.header,
36 url: options.magnolia.url + options.magnolia.pagesEndpoint,
37 errorMessage: `Attempt to get pages failed, will retry in some time...`,
38 resolverHandler: body => body.results
39 });
40}
41
42function loadDataFromMagnolia<T>(params: MagnoliaLoadingParams<T>) {
43 const operation = retry.operation(params.retryOptions);
44 return new Promise<T>(resolve => {
45 operation.attempt(() => {
46 request.get(
47 params.url,
48 {
49 json: true,
50 headers: {
51 Authorization: params.authHeader,
52 "User-Agent": "Paperboy"
53 },
54 timeout: 60 * 1000
55 },
56 (error, response, body: T) => {
57 const operationError =
58 error ||
59 (response && response.statusCode !== 200
60 ? new Error(`Return code was: ${response.statusCode}`)
61 : undefined);
62
63 if (operation.retry(operationError)) {
64 console.error(params.errorMessage);
65
66 if (error) {
67 console.error(error);
68 }
69
70 return;
71 }
72
73 resolve(params.resolverHandler(body));
74 }
75 );
76 });
77 });
78}
79
80export function writePagesFile(
81 pages: any[],
82 options?: MagnoliaSourceOptions
83): Promise<void> {
84 return new Promise((resolve, reject) => {
85 if (!fs.existsSync(options.output.json)) {
86 fs.mkdirSync(options.output.json);
87 }
88
89 fs.writeFile(
90 options.output.json + "/pages.json",
91 JSON.stringify(pages),
92 err => {
93 if (err) {
94 reject(err);
95 }
96
97 resolve();
98 }
99 );
100 });
101}
102
103export function writeWorkspaceFile(
104 workspace: string,
105 workspaceData: any,
106 options?: MagnoliaSourceOptions
107): Promise<void> {
108 return new Promise((resolve, reject) => {
109 if (!fs.existsSync(options.output.json)) {
110 fs.mkdirSync(options.output.json);
111 }
112
113 fs.writeFile(
114 options.output.json + "/" + workspace + ".json",
115 JSON.stringify(workspaceData),
116 err => {
117 if (err) {
118 reject(err);
119 }
120
121 resolve();
122 }
123 );
124 });
125}
126
127export function sanitizeJson(
128 json: any,
129 damAssets: any[],
130 pages: any,
131 sourceOptions: MagnoliaSourceOptions,
132 workspaces: { [workspace: string]: any } = {}
133): any {
134 const sanitized: any = {};
135
136 if (json) {
137 Object.keys(json).forEach(key => {
138 const isKeyExcluded =
139 sourceOptions &&
140 sourceOptions.output.excludedProperties &&
141 sourceOptions.output.excludedProperties.findIndex(
142 prop => prop === key
143 ) > -1;
144
145 if (!isKeyExcluded && key === "@nodes") {
146 const contentOrder: string[] = json[key];
147
148 if (contentOrder.length > 0) {
149 sanitized[key.substr(1)] = contentOrder.map(contentKeyIndex =>
150 sanitizeJson(
151 json[contentKeyIndex],
152 damAssets,
153 pages,
154 sourceOptions,
155 workspaces
156 )
157 );
158 }
159 } else if (!isKeyExcluded && key !== "content" && !key.match(/^\d+$/)) {
160 const originalKey = key;
161 const sanitizedKey = key
162 .replace(/^@/, "")
163 .replace(/^mgnl:/, "")
164 .replace(/^jcr:uuid/, "id");
165
166 if (!sanitizedKey.match(/^jcr:/)) {
167 if (typeof json[key] === "object" && !Array.isArray(json[key])) {
168 sanitized[sanitizedKey] = sanitizeJson(
169 json[key],
170 damAssets,
171 pages,
172 sourceOptions,
173 workspaces
174 );
175 } else {
176 let items = Array.isArray(json[key]) ? json[key] : [json[key]];
177
178 items = items.map((item: any) => {
179 if (
180 item.match(
181 /^jcr:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/
182 )
183 ) {
184 const uuid = item.replace("jcr:", "");
185 return damAssets.find(
186 damAsset => damAsset && damAsset.id === uuid
187 );
188 } else if (
189 !originalKey.match(/^@/) &&
190 !originalKey.match(/^jcr:uuid/) &&
191 item.match(
192 /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/
193 )
194 ) {
195 const node = getPopulatedNode(item, pages);
196 let value: any;
197
198 if (node) {
199 value = Object.assign(node || {}, {
200 workspace: "website"
201 });
202 } else {
203 const asset = getPopulatedNode(item, damAssets);
204
205 if (asset) {
206 value = Object.assign(asset || {}, {
207 workspace: "dam"
208 });
209 } else {
210 value = {};
211 Object.keys(workspaces)
212 .forEach(key => {
213 const foundItem = getPopulatedNode(item, workspaces[key]);
214 if (foundItem) {
215 value = Object.assign({}, foundItem, { workspace: key });
216 }
217 });
218 }
219 }
220
221 return value;
222 } else {
223 return item;
224 }
225 });
226
227 sanitized[sanitizedKey] = Array.isArray(json[key])
228 ? items
229 : items[0];
230 }
231 }
232 }
233 });
234 }
235
236 return sanitized;
237}
238
239export function getPopulatedNode(
240 id: string,
241 source: any,
242 populatedNode?: any
243): any {
244 if (populatedNode || !source) {
245 return populatedNode;
246 } else {
247 if (source["jcr:uuid"] === id || source.id === id) {
248 populatedNode = {
249 id,
250 path: source["@path"] || source.path
251 };
252 } else {
253 Object.keys(source).forEach(key => {
254 if (source[key] && typeof source[key] === "object") {
255 populatedNode = getPopulatedNode(id, source[key], populatedNode);
256 }
257 });
258 }
259
260 return populatedNode;
261 }
262}