microcms_sdk_generator
Version:
A type-safe MicroCMS SDK Generator
78 lines (77 loc) • 3.41 kB
JavaScript
import { match } from "ts-pattern";
import { format } from "prettier";
import { customFieldTypeName, customFieldTypeSchemaName, defTypeName, defTypeSchemaName, } from "./helper.js";
function fieldToImpl(endpointName, field, customFields) {
return `"${field.fieldId}": ${match(field)
.with({ kind: "text" }, () => `z.string()`)
.with({ kind: "textArea" }, () => `z.string()`)
.with({ kind: "richEditorV2" }, () => `z.string()`)
.with({ kind: "media" }, () => `z.object({
url: z.string().url(),
height: z.number(),
width: z.number(),
})`)
.with({ kind: "mediaList" }, () => `z.array(z.object({
url: z.string().url(),
height: z.number(),
width: z.number(),
}))`)
.with({ kind: "date" }, () => `z.string().datetime()`)
.with({ kind: "boolean" }, () => `z.boolean()`)
.with({ kind: "select", multipleSelect: false }, (field) => `z.tuple([z.enum([
${field.selectItems.map((o) => `"${o.value}"`).join(",")}
])])`)
.with({ kind: "select", multipleSelect: true }, (field) => `z.array(z.enum([
${field.selectItems.map((o) => `"${o.value}"`).join(",")}
]))`)
.with({ kind: "number" }, () => `z.number()`)
.with({ kind: "relation" }, () => `OnlyIdSchema.and(z.unknown())`)
.with({ kind: "relationList" }, () => `z.array(OnlyIdSchema.and(z.unknown()))`)
.with({ kind: "custom" }, (field) => {
const customField = customFields.find((c) => c.createdAt === field.customFieldCreatedAt);
if (!customField) {
return `z.unknown()`;
}
return customFieldTypeSchemaName(endpointName, customField.fieldId);
})
.with({ kind: "repeater" }, (field) => {
let schema = customFields
.filter((c) => field.customFieldCreatedAtList.includes(c.createdAt))
.map((c) => customFieldTypeSchemaName(endpointName, c.fieldId))
.join(",");
if (field.customFieldCreatedAtList.length > 1) {
schema = `z.unknown([${schema}])`;
}
return `z.array(${schema})`;
})
.exhaustive()
.trim()}${field.required ? "" : ".optional()"},`;
}
function customFieldToSchema(endpointName, customField) {
const schemaName = customFieldTypeSchemaName(endpointName, customField.fieldId);
const typeName = customFieldTypeName(endpointName, customField.fieldId);
return `// eslint-disable-next-line @typescript-eslint/naming-convention
export const ${schemaName} = z.object({
fieldId: z.string(),
${customField.fields
.map((field) => fieldToImpl(endpointName, field, []))
.join("\n")}})
// eslint-disable-next-line @typescript-eslint/naming-convention
export type ${typeName} = z.infer<typeof ${schemaName}>
`;
}
export async function printDefTypeImpl({ endpointName, apiSchema, }) {
return await format(`
${apiSchema.customFields
.map((c) => customFieldToSchema(endpointName, c))
.join("\n")}
export const ${defTypeSchemaName(endpointName)} = z.object({
${apiSchema.apiFields
.map((field) => fieldToImpl(endpointName, field, apiSchema.customFields))
.join("\n")}
})
export type ${defTypeName(endpointName)} = z.infer<typeof ${defTypeSchemaName(endpointName)}>
`, {
parser: "typescript",
});
}