strapi-plugin-generic-custom-fields
Version:
This plugin allows you to easily add custom fields to Strapi.
358 lines (357 loc) • 10.8 kB
JavaScript
;
const slugify = require("slugify");
const zod = require("zod");
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
const slugify__default = /* @__PURE__ */ _interopDefault(slugify);
const bootstrap = ({ strapi: _strapi }) => {
};
const destroy = ({ strapi: _strapi }) => {
};
const strapi = {
name: "generic-custom-fields"
};
const packageJson = {
strapi
};
const PLUGIN_ID = packageJson.strapi.name;
const register = ({ strapi: strapi2 }) => {
const configCustomFields = strapi2.plugin(PLUGIN_ID).config("customFields");
for (const customField of configCustomFields) {
strapi2.customFields.register({
name: slugify__default.default(customField.name, { lower: true }),
plugin: PLUGIN_ID,
type: "string",
inputSize: customField.inputSize
});
}
};
const itemResponseSchema = zod.z.object({
value: zod.z.string().min(1),
label: zod.z.string().min(1),
icon: zod.z.object({
src: zod.z.string(),
colorMask: zod.z.boolean().optional()
}).optional()
});
const itemsResponseSchema = zod.z.object({
items: zod.z.array(itemResponseSchema)
// total: z.number().int().min(0).optional(),
});
const customFieldSchema = zod.z.object({
name: zod.z.string().min(1),
description: zod.z.string().min(1).optional(),
icon: zod.z.union([
zod.z.literal("Alien"),
zod.z.literal("Archive"),
zod.z.literal("ArrowClockwise"),
zod.z.literal("ArrowDown"),
zod.z.literal("ArrowLeft"),
zod.z.literal("ArrowLineLeft"),
zod.z.literal("ArrowLineRight"),
zod.z.literal("ArrowRight"),
zod.z.literal("ArrowUp"),
zod.z.literal("ArrowsCounterClockwise"),
zod.z.literal("ArrowsOut"),
zod.z.literal("Bell"),
zod.z.literal("Bold"),
zod.z.literal("Book"),
zod.z.literal("Briefcase"),
zod.z.literal("BulletList"),
zod.z.literal("Calendar"),
zod.z.literal("Car"),
zod.z.literal("CaretDown"),
zod.z.literal("CaretUp"),
zod.z.literal("Cast"),
zod.z.literal("CastleTurret"),
zod.z.literal("ChartBubble"),
zod.z.literal("ChartCircle"),
zod.z.literal("ChartPie"),
zod.z.literal("Check"),
zod.z.literal("CheckCircle"),
zod.z.literal("CheckCircleEmpty"),
zod.z.literal("ChevronDown"),
zod.z.literal("ChevronLeft"),
zod.z.literal("ChevronRight"),
zod.z.literal("ChevronUp"),
zod.z.literal("Clock"),
zod.z.literal("ClockCounterClockwise"),
zod.z.literal("Cloud"),
zod.z.literal("CloudUpload"),
zod.z.literal("Code"),
zod.z.literal("CodeBlock"),
zod.z.literal("Coffee"),
zod.z.literal("Cog"),
zod.z.literal("Collapse"),
zod.z.literal("Command"),
zod.z.literal("Crop"),
zod.z.literal("Cross"),
zod.z.literal("CrossCircle"),
zod.z.literal("Crown"),
zod.z.literal("Cursor"),
zod.z.literal("Database"),
zod.z.literal("Discuss"),
zod.z.literal("Download"),
zod.z.literal("Drag"),
zod.z.literal("Duplicate"),
zod.z.literal("Earth"),
zod.z.literal("EarthStriked"),
zod.z.literal("EmotionHappy"),
zod.z.literal("EmotionUnhappy"),
zod.z.literal("Expand"),
zod.z.literal("ExternalLink"),
zod.z.literal("Eye"),
zod.z.literal("EyeStriked"),
zod.z.literal("Faders"),
zod.z.literal("Feather"),
zod.z.literal("File"),
zod.z.literal("FileCsv"),
zod.z.literal("FileError"),
zod.z.literal("FilePdf"),
zod.z.literal("FileXls"),
zod.z.literal("FileZip"),
zod.z.literal("Filter"),
zod.z.literal("Folder"),
zod.z.literal("Gift"),
zod.z.literal("Globe"),
zod.z.literal("GraphQl"),
zod.z.literal("GridFour"),
zod.z.literal("GridNine"),
zod.z.literal("HandHeart"),
zod.z.literal("Hashtag"),
zod.z.literal("HeadingFive"),
zod.z.literal("HeadingFour"),
zod.z.literal("HeadingOne"),
zod.z.literal("HeadingSix"),
zod.z.literal("HeadingThree"),
zod.z.literal("HeadingTwo"),
zod.z.literal("Headphones"),
zod.z.literal("Heart"),
zod.z.literal("House"),
zod.z.literal("Image"),
zod.z.literal("Images"),
zod.z.literal("IndentDecrease"),
zod.z.literal("IndentIncrease"),
zod.z.literal("Information"),
zod.z.literal("Italic"),
zod.z.literal("Key"),
zod.z.literal("Layout"),
zod.z.literal("Lightbulb"),
zod.z.literal("Lightning"),
zod.z.literal("Link"),
zod.z.literal("List"),
zod.z.literal("ListPlus"),
zod.z.literal("ListSearch"),
zod.z.literal("Loader"),
zod.z.literal("Lock"),
zod.z.literal("Magic"),
zod.z.literal("Mail"),
zod.z.literal("ManyToMany"),
zod.z.literal("ManyToOne"),
zod.z.literal("ManyWays"),
zod.z.literal("Message"),
zod.z.literal("Microphone"),
zod.z.literal("Minus"),
zod.z.literal("MinusCircle"),
zod.z.literal("Monitor"),
zod.z.literal("Moon"),
zod.z.literal("More"),
zod.z.literal("Move"),
zod.z.literal("MusicNotes"),
zod.z.literal("NumberList"),
zod.z.literal("OneToMany"),
zod.z.literal("OneToOne"),
zod.z.literal("OneWay"),
zod.z.literal("PaintBrush"),
zod.z.literal("PaintRoller"),
zod.z.literal("Palette"),
zod.z.literal("PaperPlane"),
zod.z.literal("Paperclip"),
zod.z.literal("Paragraph"),
zod.z.literal("Pencil"),
zod.z.literal("Phone"),
zod.z.literal("Pin"),
zod.z.literal("PinMap"),
zod.z.literal("Plane"),
zod.z.literal("Plant"),
zod.z.literal("Play"),
zod.z.literal("Plus"),
zod.z.literal("PlusCircle"),
zod.z.literal("PresentationChart"),
zod.z.literal("PriceTag"),
zod.z.literal("PuzzlePiece"),
zod.z.literal("Question"),
zod.z.literal("Quotes"),
zod.z.literal("Restaurant"),
zod.z.literal("Rocket"),
zod.z.literal("Scissors"),
zod.z.literal("SealCheck"),
zod.z.literal("Search"),
zod.z.literal("Server"),
zod.z.literal("Shield"),
zod.z.literal("Shirt"),
zod.z.literal("ShoppingCart"),
zod.z.literal("SignOut"),
zod.z.literal("SlidersHorizontal"),
zod.z.literal("Sparkle"),
zod.z.literal("SquaresFour"),
zod.z.literal("Stack"),
zod.z.literal("Star"),
zod.z.literal("Stethoscope"),
zod.z.literal("Stop"),
zod.z.literal("Store"),
zod.z.literal("StrikeThrough"),
zod.z.literal("Sun"),
zod.z.literal("Television"),
zod.z.literal("ThumbDown"),
zod.z.literal("ThumbUp"),
zod.z.literal("Train"),
zod.z.literal("Trash"),
zod.z.literal("Typhoon"),
zod.z.literal("Underline"),
zod.z.literal("Upload"),
zod.z.literal("User"),
zod.z.literal("VolumeMute"),
zod.z.literal("VolumeUp"),
zod.z.literal("Walk"),
zod.z.literal("WarningCircle"),
zod.z.literal("Wheelchair")
]).optional(),
inputSize: zod.z.object({
default: zod.z.union([zod.z.literal(4), zod.z.literal(6), zod.z.literal(8), zod.z.literal(12)]),
isResizable: zod.z.boolean()
}).optional(),
searchable: zod.z.boolean().optional(),
fetchItems: zod.z.function().args(zod.z.object({
query: zod.z.string().optional()
})).returns(zod.z.union([itemsResponseSchema, zod.z.promise(itemsResponseSchema)])),
fetchItem: zod.z.function().args(zod.z.object({
value: zod.z.string()
})).returns(zod.z.union([itemResponseSchema, zod.z.promise(itemResponseSchema)]))
});
const configSchema = zod.z.object({
customFields: zod.z.array(customFieldSchema).refine(
(fields) => {
const slugifiedNames = fields.map((field) => slugify__default.default(field.name, { lower: true }));
return new Set(slugifiedNames).size === slugifiedNames.length;
},
{
message: "Each custom field name must be unique after slugification"
}
)
});
const config = {
default: {
customFields: []
},
validator(config2) {
configSchema.parse(config2);
}
};
const contentTypes = {};
const controller = ({ strapi: strapi2 }) => ({
getConfigCustomFields() {
return strapi2.plugin(PLUGIN_ID).config("customFields");
},
getCustomFieldUID(name) {
return `plugin::${PLUGIN_ID}.${slugify__default.default(name, { lower: true })}`;
},
configCustomFields() {
return this.getConfigCustomFields();
},
configCustomField(ctx) {
const customFields = this.getConfigCustomFields();
const customField = customFields.find((field) => ctx.params.uid === this.getCustomFieldUID(field.name));
if (!customField) {
ctx.throw(404, `Custom field ${ctx.params.uid} not found`);
}
return customField;
},
async customFieldItems(ctx) {
try {
const customFields = this.getConfigCustomFields();
const customField = customFields.find((field) => ctx.params.uid === this.getCustomFieldUID(field.name));
if (!customField) {
ctx.throw(404, `Custom field ${ctx.params.uid} not found`);
}
const query = ctx.request.query.query;
return itemsResponseSchema.parse(await customField.fetchItems({
query
// page: page ? parseInt(page, 10) : undefined,
}));
} catch (error) {
throw error instanceof Error ? error : new Error(`Error fetching CustomField[${ctx.params.uid}] items: ${error}`);
}
},
async customFieldItem(ctx) {
try {
const customFields = this.getConfigCustomFields();
const customField = customFields.find((field) => ctx.params.uid === this.getCustomFieldUID(field.name));
if (!customField) {
ctx.throw(404, `Custom field ${ctx.params.uid} not found`);
}
const value = ctx.request.query.value;
return itemResponseSchema.parse(await customField.fetchItem({ value }));
} catch (error) {
throw error instanceof Error ? error : new Error(`Error fetching CustomField[${ctx.params.uid}] item: ${error}`);
}
}
});
const controllers = {
admin: controller
};
const middlewares = {};
const policies = {};
const adminRoutes = [
{
method: "GET",
path: "/config/custom-fields",
handler: "admin.configCustomFields",
config: {
policies: ["admin::isAuthenticatedAdmin"]
}
},
{
method: "GET",
path: "/config/custom-fields/:uid",
handler: "admin.configCustomField",
config: {
policies: ["admin::isAuthenticatedAdmin"]
}
},
{
method: "GET",
path: "/custom-fields/:uid/items",
handler: "admin.customFieldItems",
config: {
policies: ["admin::isAuthenticatedAdmin"]
}
},
{
method: "GET",
path: "/custom-fields/:uid/item",
handler: "admin.customFieldItem",
config: {
policies: ["admin::isAuthenticatedAdmin"]
}
}
];
const routes = {
admin: {
type: "admin",
routes: adminRoutes
}
};
const services = {};
const index = {
register,
bootstrap,
destroy,
config,
controllers,
routes,
services,
contentTypes,
policies,
middlewares
};
module.exports = index;