@flotiq/flotiq-astro-sdk
Version:
Astro collection generator for connecting with Flotiq CMS
225 lines (214 loc) • 9.13 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.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;