Skip to content

Commit

Permalink
#704 - Fix in zod optional check
Browse files Browse the repository at this point in the history
  • Loading branch information
estruyf committed Nov 11, 2023
1 parent 8db76ab commit 11354ad
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 59 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
- [#696](https://github.com/estruyf/vscode-front-matter/issues/696): Close the local server terminal on restart
- [#699](https://github.com/estruyf/vscode-front-matter/issues/699): Changing border theme variable for the dashboard header
- [#703](https://github.com/estruyf/vscode-front-matter/issues/703): Fix retrieval of Astro Collections for `pnpm` projects
- [#704](https://github.com/estruyf/vscode-front-matter/issues/704): Fix `zod` schema script for optional fields

## [9.3.1] - 2023-10-27

Expand Down
116 changes: 57 additions & 59 deletions ssg-scripts/astro.collections.mjs
Original file line number Diff line number Diff line change
@@ -1,32 +1,24 @@
import { writeFileSync } from "fs";
import { join } from "path";
import { createServer } from "vite";
import zod from "astro/zod";

const {
ZodDefault,
ZodObject,
ZodOptional,
ZodString,
ZodEffects,
ZodEnum
} = zod;
import { writeFileSync } from 'fs';
import { join } from 'path';
import { createServer } from 'vite';
import zod from 'astro/zod';

const { ZodDefault, ZodObject, ZodOptional, ZodString, ZodEffects, ZodEnum } = zod;

/**
* Process the Zod field
* @param {ZodTypeAny} field
* @param {string} defaultValue
* @returns
* @param {ZodTypeAny} field
* @param {boolean} isOptional
* @param {string} defaultValue
* @returns
*/
function getField(field, defaultValue = undefined) {
let isOptional = false;

function getField(field, isOptional = false, defaultValue = undefined) {
// Handle various type transformations and assignments
if (field instanceof ZodOptional) {
isOptional = true;
const type = field.unwrap();

return getField(type, isOptional, defaultValue)
return getField(type, isOptional, defaultValue);
}

if (field instanceof ZodDefault) {
Expand All @@ -35,43 +27,43 @@ function getField(field, defaultValue = undefined) {
defaultValue = field.parse(undefined);
// https://github.com/sachinraja/zod-to-ts/blob/main/src/index.ts
const type = field._def.innerType;
return getField(type, isOptional, defaultValue)
return getField(type, isOptional, defaultValue);
}

return {
type: field,
isOptional,
defaultValue
}
};
}

/**
* Generate the field information
* @param {string} name
* @param {ZodTypeAny} type
* @returns
* @param {string} name
* @param {ZodTypeAny} type
* @returns
*/
function generateFieldInfo(name, type) {
let description = type.description;
let defaultValue = undefined;

const {
type: fieldType,
isOptional: isFieldOptional,
defaultValue: fieldDefaultValue
} = getField(type, defaultValue);
const {
type: fieldType,
isOptional: isFieldOptional,
defaultValue: fieldDefaultValue
} = getField(type, false, defaultValue);

const fieldInfo = {
name: name,
description: description,
defaultValue: fieldDefaultValue,
type: fieldType._def.typeName,
required: !isFieldOptional,
required: !isFieldOptional
};

if (fieldType instanceof ZodObject) {
const subFields = extractFieldInfoFromShape(fieldType);

fieldInfo.fields = subFields;
}

Expand All @@ -96,8 +88,8 @@ function generateFieldInfo(name, type) {

/**
* Parse the scheme into an array of fields
* @param {ZodTypeAny} type
* @returns
* @param {ZodTypeAny} type
* @returns
*/
function extractFieldInfoFromShape(type) {
if (type instanceof ZodOptional) {
Expand All @@ -106,7 +98,7 @@ function extractFieldInfoFromShape(type) {

if (!(type instanceof ZodObject)) {
// Return an empty array if the type is not of the expected type
return [];
return [];
}

// Iterate through the shape properties
Expand All @@ -121,41 +113,44 @@ function extractFieldInfoFromShape(type) {

/**
* Process each content collection
* @param {*} collections
* @returns
* @param {*} collections
* @returns
*/
function processCollection(collections) {
if (!Array.isArray(collections)) {
return [];
}

return collections.map(([name, collection]) => {
const schema = typeof collection.schema === "function" ? collection.schema({
image() {
const field = zod.string();
field.fmFieldType = "image";
return field;
}
}) : collection.schema;
const schema =
typeof collection.schema === 'function'
? collection.schema({
image() {
const field = zod.string();
field.fmFieldType = 'image';
return field;
}
})
: collection.schema;

return {
name,
type: collection.type || "content",
fields: extractFieldInfoFromShape(schema),
type: collection.type || 'content',
fields: extractFieldInfoFromShape(schema)
};
});
}

/**
* More info: https://vitejs.dev/guide/api-plugin.html#virtual-modules-convention
* @returns
* @returns
*/
const astroContentModulePlugin = () => {
const astroContent = "astro:content";
const astroContent = 'astro:content';
const astroContentMarker = `\0${astroContent}`;

return {
name: "astro-content-collections",
name: 'astro-content-collections',
resolveId(importee) {
if (importee === astroContent) {
return astroContentMarker;
Expand All @@ -174,16 +169,16 @@ const astroContentModulePlugin = () => {
`;
}
}
}
};
};

/**
* Start of the Astro Collections script
*/
(async () => {
const configPath = process.argv[2];
if (!configPath || typeof configPath !== "string") {
console.log("No config path provided");
if (!configPath || typeof configPath !== 'string') {
console.log('No config path provided');
process.exit(1);
}

Expand All @@ -195,27 +190,30 @@ const astroContentModulePlugin = () => {
hmr: false
},
optimizeDeps: {
disabled: true,
disabled: true
},
appType: "custom",
appType: 'custom',
plugins: [astroContentModulePlugin()]
});

try {
// https://github.dev/withastro/astro/blob/defab70cb2a0c67d5e9153542490d2749046b151/packages/astro/src/content/utils.ts#L334
const contentModule = await server.ssrLoadModule(configPath)
const contentModule = await server.ssrLoadModule(configPath);

const collections = Object.entries(contentModule.collections ?? {});
const processedCollections = processCollection(collections);

writeFileSync(join(process.cwd(), `./.frontmatter/temp/astro.collections.json`), JSON.stringify(processedCollections));

console.log("Collections generated successfully");
writeFileSync(
join(process.cwd(), `./.frontmatter/temp/astro.collections.json`),
JSON.stringify(processedCollections)
);

console.log('Collections generated successfully');
process.exit(0);
} catch (error) {
console.log(error.message);
process.exit(1);
} finally {
await server.close();
}
})();
})();

0 comments on commit 11354ad

Please sign in to comment.