@archer-edu/dxp-directus-cli
Version:
252 lines • 11.3 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.writeBlogIndex = exports.writeBlogPost = exports.mapPost = exports.getPosts = void 0;
const api_1 = require("./support/api");
const utils_1 = require("./support/utils");
const config_1 = require("./support/config");
const js_yaml_1 = __importDefault(require("js-yaml"));
const register = (program) => {
program
.command("pull-blog <siteId>")
.alias("b")
.description("Pull site's blog posts to the 'blog' directory inside content")
.option("-b, --blog-dir <dir>", "Change the 'blog' path. This directory is relative to content directory", "blog")
.option("-d, --debug", "Enable debug mode")
.option("-c, --continue", "Continue on error (lax-mode for previews)")
.option("-r, --redirect [redirect]", "Add a global redirect for each of the blog entries, relative to their path (slug/redirect)")
.option("-i, --download-images <imageDir>", "Download images to a directory (ie 'assets/images'). If omitted, images use the CDN.")
.option("-t, --tag <tag>", "Version tag of the blogs to pull")
.action((siteId, options) => __awaiter(void 0, void 0, void 0, function* () {
const { blogDir = 'blog', debug = false, downloadImages, redirect, continue: cont, tag } = options;
const postPath = `${config_1.contentPath}/${blogDir}`;
(0, utils_1.assertDirectory)(postPath);
if (debug)
console.log(`Pulling blog posts from site ${siteId} to ${postPath}`);
if (downloadImages && debug)
console.log(`Downloading images to ${downloadImages}`);
const writtenFiles = yield pullBlogPosts({ siteId, blogDir, debug, downloadImages, redirect, continue: cont, tag });
const fileFormat = new RegExp("^.*/_.*.md$");
const deleted = (0, utils_1.deleteFiles)(postPath, (f) => !writtenFiles.includes(f) && !fileFormat.test(f));
if (debug) {
console.log(`Deleted ${deleted.length} files`);
console.table(deleted);
}
}));
};
exports.default = register;
const pullBlogPosts = ({ siteId, blogDir, downloadImages, redirect, debug, tag, continue: cont }) => __awaiter(void 0, void 0, void 0, function* () {
const postPath = `${config_1.contentPath}/${blogDir}`;
const imagePath = downloadImages ? (0, utils_1.fixRelativePath)(downloadImages) : null;
const posts = yield getPosts(siteId, tag, imagePath, debug, cont);
if (debug) {
console.log(`Read ${posts.length} posts`);
}
const writtenFiles = posts.map((post) => writeBlogPost(postPath, post, redirect));
if (debug) {
console.log(`Wrote ${writtenFiles.length} posts to disk`);
console.dir(writtenFiles);
}
writtenFiles.push(writeBlogIndex(blogDir, posts));
console.log(`Pulled ${posts.length} blog entries from directus`);
return writtenFiles;
});
const postsQuery = (siteId, limit, offset) => `{
entries: site_entry(
filter: { site_id: { key: { _eq: "${siteId}" }}},
limit: ${limit},
offset: ${offset}
) {
id
}
}`;
const postVersionQuery = (id, tag) => `{
entry: site_entry_by_id(
id: "${id}",
version: "${tag}"
) {
id
title
slug
description
description_twitter
description_facebook
headline
content
author
sources
front_matter
image {
id
title
type
filename_download
filename_disk
}
image_thumbnail {
id
title
type
filename_download
filename_disk
}
categories {
site_entry_categories_id {
name
}
}
tags {
site_entry_tags_id {
name
}
}
json_ld
published
status
}
}`;
function getPosts(siteId, tag, downloadImages, debug = false, cont = false) {
return __awaiter(this, void 0, void 0, function* () {
let allEntries = [];
let offset = 0;
const limit = 100;
let hasMore = true;
while (hasMore) {
try {
const { entries = [] } = yield (0, api_1.graphRequest)(config_1.queryPath, postsQuery(siteId, limit, offset), debug);
allEntries = allEntries.concat(entries);
if (debug)
console.log(`Fetched ${entries.length} entries, offset ${offset}`);
if (entries.length < limit)
hasMore = false;
else
offset += limit;
}
catch (e) {
console.error(`An error occurred while fetching posts: ${e.message}`);
if (!cont)
throw e;
hasMore = false;
}
}
// Process each entry
return Promise.all(allEntries.map((item, index) => __awaiter(this, void 0, void 0, function* () {
try {
// pull each item with the version param
// if there's a version with this tag, it will be pulled
// otherwise, the main version will be pulled
if (debug)
console.log(`Fetching entry ${item.id} with tag ${tag}`);
const { entry } = yield (0, api_1.graphRequest)(config_1.queryPath, postVersionQuery(item.id, tag), debug);
const mappedEntry = yield mapPost(index, entry, downloadImages);
const { metadata } = mappedEntry;
if (debug)
console.dir({ metadata });
return mappedEntry;
}
catch (e) {
console.error(e);
if (!cont)
throw e;
return null;
}
}))).then(posts => posts.filter(p => p != null));
});
}
exports.getPosts = getPosts;
function mapPost(index, item, downloadImages, cont = false) {
return __awaiter(this, void 0, void 0, function* () {
const { id, title, description, description_twitter, description_facebook, headline, slug, json_ld, published, status, content: rawContent, image, image_thumbnail, tags, categories, author, sources, front_matter } = item;
let imagePath = null;
let thumbnailPath = null;
let content = rawContent;
let parsedMetadata = { sections: [], redirects: [] };
try {
content = yield (0, utils_1.fixImages)(rawContent, downloadImages);
imagePath = image ? yield (0, utils_1.fixImage)(image.id, downloadImages) : null;
thumbnailPath = image_thumbnail ? yield (0, utils_1.fixImage)(image_thumbnail === null || image_thumbnail === void 0 ? void 0 : image_thumbnail.id, downloadImages) : null;
parsedMetadata = (front_matter ? js_yaml_1.default.load((0, utils_1.cleanFrontMatter)(front_matter), {
onWarning: (e) => {
console.warn(e, {
front_matter
});
}
}) : { sections: [], redirects: [] });
}
catch (e) {
console.error(e, {
front_matter
});
if (!cont)
throw e;
}
const post = {
file_path: `${index}-${slug}.md`,
content,
sources,
metadata: (0, utils_1.cleanObject)(Object.assign({ id,
title, description: (0, utils_1.stripNewLines)(description), description_twitter,
description_facebook,
headline,
slug,
json_ld, published: status == 'approved' ? published : undefined, draft: status == 'draft' || undefined, image: imagePath || thumbnailPath ? {
src: (imagePath || thumbnailPath),
alt: (image === null || image === void 0 ? void 0 : image.description) || (image === null || image === void 0 ? void 0 : image.title) || ((image_thumbnail === null || image_thumbnail === void 0 ? void 0 : image_thumbnail.description) || (image_thumbnail === null || image_thumbnail === void 0 ? void 0 : image_thumbnail.title))
} : undefined, image_thumbnail: thumbnailPath || imagePath ? {
src: (thumbnailPath || imagePath),
alt: image_thumbnail ? (image_thumbnail.description || image_thumbnail.title) : (image === null || image === void 0 ? void 0 : image.description) || (image === null || image === void 0 ? void 0 : image.title),
} : undefined, tags: tags === null || tags === void 0 ? void 0 : tags.map(c => c.site_entry_tags_id.name), categories: categories === null || categories === void 0 ? void 0 : categories.map(c => c.site_entry_categories_id.name), authors: author ? [author] : [] }, parsedMetadata))
};
if (post.metadata.redirects == undefined)
post.metadata.redirects = [];
if (post.metadata.sections == undefined)
post.metadata.sections = [];
return post;
});
}
exports.mapPost = mapPost;
function writeBlogPost(blogPath, post, alias) {
var _a;
const { content, file_path, metadata, sources } = post;
if (alias)
metadata.redirects.push(`${metadata.slug}/${alias}`);
if (!((_a = metadata.redirects) === null || _a === void 0 ? void 0 : _a.length))
delete metadata.redirects;
const renderedSources = (sources === null || sources === void 0 ? void 0 : sources.map(utils_1.renderSource).join('\n')) || '';
return (0, utils_1.writeFile)(`${blogPath}/${file_path}`, `---\n${js_yaml_1.default.dump(metadata, {
lineWidth: -1,
})}\n---\n${content}\n\n${renderedSources}`.trim());
}
exports.writeBlogPost = writeBlogPost;
function writeBlogIndex(blogDir, entries) {
const searchIndex = entries.map(post => {
const { content, metadata: { slug, headline, title, description, authors, categories, tags } } = post;
return {
title: title,
url: `/${blogDir}/${slug}/`,
text: [
content,
headline,
title,
description,
...authors,
...categories,
...tags
].join(' ')
};
});
return (0, utils_1.writeFile)(`${config_1.basePath}/static/index.json`, JSON.stringify(searchIndex, null, 2));
}
exports.writeBlogIndex = writeBlogIndex;
//# sourceMappingURL=pull-blog.js.map