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