UNPKG

@flotiq/flotiq-astro-sdk

Version:

Astro collection generator for connecting with Flotiq CMS

225 lines (214 loc) 9.13 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.makeMarkdownHelp = exports.handler = exports.builder = exports.describe = exports.command = void 0; const fs_1 = require("fs"); const prettier_1 = __importDefault(require("prettier")); const path_1 = require("path"); const ctd_types_1 = require("../ctd-types"); exports.command = ["$0", "flotiq-astro-typegen"]; exports.describe = `flotiq-astro-typegen Generates Astro collections for Flotiq API based on the content type definitions on your account`; const builder = (cmd) => { var _a; cmd .option("flotiq-key", { describe: "Flotiq API key with read only access", type: "string", demandOption: !process.env.FLOTIQ_API_KEY, default: process.env.FLOTIQ_API_KEY, }) .option("flotiq-api-url", { describe: "Url to the Flotiq API", type: "string", default: (_a = process.env.FLOTIQ_API_URL) !== null && _a !== void 0 ? _a : "https://api.flotiq.com", }) .option("output", { describe: "Path to target filename", type: "string", default: "./src/content.config.ts", }) .option("watch", { describe: "Watch for changes in the content type definitions and regenerate collections", type: "boolean", default: false, }); }; exports.builder = builder; function generateApiCollections(args) { const apiUrl = args.flotiqApiUrl.replace(/\/{1,10}$/, ""); const apiKey = args.flotiqKey; function getCTDS() { return __awaiter(this, arguments, void 0, function* (page = 1, internal = 0) { return yield fetch(`${apiUrl}/api/v1/internal/contenttype?limit=1000&page=${page}&internal=${internal}`, { headers: { "X-AUTH-TOKEN": apiKey, }, }).then((response) => response.json()); }); } function getAllCtds() { return __awaiter(this, void 0, void 0, function* () { let page = 1; let result; const data = []; do { result = yield getCTDS(page); data.push(...((result === null || result === void 0 ? void 0 : result.data) || [])); page++; } while (result.total_pages > result.current_page); page = 1; do { result = yield getCTDS(page, 1); data.push(...((result === null || result === void 0 ? void 0 : result.data) || [])); page++; } while (result.total_pages > result.current_page); return data.filter((t) => // Include the following types in the generated types !t.internal || ["_media", "_tag", "_webhooks", "_plugin_settings", "_generated_forms"].includes(t.name)); }); } const names = []; return getAllCtds().then((data) => __awaiter(this, void 0, void 0, function* () { const ctdTypes = data.map((contentTypeDefinition) => { names.push(contentTypeDefinition.name); const required = contentTypeDefinition.schemaDefinition.required; const order = contentTypeDefinition.metaDefinition.order; const propertiesConfig = contentTypeDefinition.metaDefinition.propertiesConfig; const schemas = contentTypeDefinition.schemaDefinition.allOf[1].properties; return (0, ctd_types_1.generateCollections)(schemas, propertiesConfig, required, order, contentTypeDefinition.name); }); const newDef = ` /** * This file was generated by flotiq-astro-typegen command * Generated at: ${new Date().toISOString()} */ import { defineCollection, z, reference } from 'astro:content'; import { Flotiq } from "@flotiq/flotiq-api-sdk"; const api = new Flotiq({ apiKey: import.meta.env.FLOTIQ_API_KEY }); function mapReferences(object: any) { Object.keys(object).forEach((key) => { if(Array.isArray(object[key])) { object[key].forEach((innerObject, index) => { if(innerObject.dataUrl) { const [,,,,type,id] = innerObject.dataUrl.split('/'); object[key][index] = {id: id, collection: type}; } else { object[key][index] = mapReferences(innerObject); } }) } }) return object; } ${ctdTypes.join("\n\n")} export const collections = { ${names.join(', ')} }; `; (0, fs_1.writeFileSync)((0, path_1.resolve)(args.output), yield prettier_1.default.format(newDef, { parser: "typescript", })); console.log("Types were saved to: ", args.output); })); } function getGeneratedAtDate(filename) { var _a; if (!(0, fs_1.existsSync)((0, path_1.resolve)(filename))) { return 0; } const generatedFileContents = (0, fs_1.readFileSync)((0, path_1.resolve)(filename), "utf-8"); const generatedAt = (_a = generatedFileContents.match(/Generated at: (.*)/)) === null || _a === void 0 ? void 0 : _a[1]; return generatedAt ? new Date(generatedAt).getTime() : 0; } function getLastCTDChangeDate(args) { return __awaiter(this, void 0, void 0, function* () { const apiUrl = args.flotiqApiUrl.replace(/\/{1,10}$/, ""); const apiKey = args.flotiqKey; const dateFields = ["createdAt", "updatedAt"]; return Promise.all(dateFields.map((dateField) => __awaiter(this, void 0, void 0, function* () { const resultData = yield fetch(`${apiUrl}/api/v1/internal/contenttype?limit=1&order_by=${dateField}&order_direction=desc`, { headers: { "X-AUTH-TOKEN": apiKey, }, }).then((response) => response.json()); const firstResult = resultData.data[0]; return (firstResult === null || firstResult === void 0 ? void 0 : firstResult[dateField]) ? new Date(firstResult[dateField]).getTime() : 0; }))).then((dates) => Math.max(...dates)); }); } const handler = (args) => __awaiter(void 0, void 0, void 0, function* () { const apiKey = args.flotiqKey; if (!apiKey) { console.error("Please provide FLOTIQ_API_KEY environment variable or --flotiq-key argument"); process.exit(1); } yield generateApiCollections(args); const WATCH_INTERVAL = 30000; if (args.watch) { console.log("Watching for changes"); setInterval(() => __awaiter(void 0, void 0, void 0, function* () { const generatedAt = getGeneratedAtDate(args.output); const lastCTDChange = yield getLastCTDChangeDate(args); if (generatedAt < lastCTDChange) { console.log("Detected ctd change, regenerating types"); yield generateApiCollections(args); } }), WATCH_INTERVAL); } }); exports.handler = handler; const makeMarkdownHelp = () => { const builderInfo = {}; const builderMock = new Proxy({}, { get: (_, prop) => { return (...args) => { if (!builderInfo[prop]) { builderInfo[prop] = []; } builderInfo[prop].push(args); return builderMock; }; }, }); (0, exports.builder)(builderMock); function stringifyDefaultValue(value) { if (typeof value !== "undefined") { return `\`${value}\``; } return ""; } return `## ${exports.command .filter((c) => c != "$0") .map((c) => `\`${c}\``) .join(", ")} ${exports.describe} ### Options | Option | Description | Default | | ------ | ----------- | ------- | ${builderInfo["option"] .filter((args) => { const [_, options] = args; return !(options === null || options === void 0 ? void 0 : options.hidden); }) .map((args) => { const [name, config] = args; return `| \`--${name}\` | ${config.describe} | ${stringifyDefaultValue(config === null || config === void 0 ? void 0 : config.default)} |`; }) .join("\n")} `; }; exports.makeMarkdownHelp = makeMarkdownHelp;