UNPKG

@archer-edu/dxp-directus-cli

Version:
252 lines 11.3 kB
"use strict"; 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