Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/sour-sloths-deny.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@ascorbic/airtable-loader": patch
"@ascorbic/bluesky-loader": patch
"@ascorbic/youtube-loader": patch
"@ascorbic/loader-utils": patch
"@ascorbic/feed-loader": patch
"@ascorbic/mock-loader": patch
"@ascorbic/csv-loader": patch
---

Add Astro v6 to supported peerDependencies
6 changes: 3 additions & 3 deletions demos/loaders/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
"@ascorbic/youtube-loader": "workspace:^",
"@astro-community/astro-embed-bluesky": "^0.1.3",
"@astro-community/astro-embed-youtube": "^0.5.6",
"@astrojs/check": "^0.9.4",
"@astrojs/netlify": "^6.4.0",
"@astrojs/check": "^0.9.7",
"@astrojs/netlify": "^7.0.2",
"@atproto/api": "^0.13.31",
"@unpic/astro": "^1.0.0",
"astro": "^5.10.1",
"astro": "^6.0.4",
"typescript": "^5.7.3"
}
}
7 changes: 4 additions & 3 deletions packages/airtable/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.17.3",
"astro": "^5.10.1",
"astro": "^6.0.8",
"publint": "^0.3.2",
"tsup": "^8.3.6",
"typescript": "^5.7.3"
},
"peerDependencies": {
"astro": "^4.14.0 || ^5.0.0"
"astro": "^4.14.0 || ^5.0.0 || ^6.0.0"
},
"keywords": [
"withastro",
Expand All @@ -43,6 +43,7 @@
"dependencies": {
"@ascorbic/loader-utils": "workspace:^",
"airtable": "^0.12.2",
"ts-pattern": "^5.6.2"
"ts-pattern": "^5.6.2",
"zod-to-ts": "^1.2.0"
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zod-to-ts v2.0.0 is available, but the API is different from what the Astro docs expect. Since Astro v5 used zod-to-ts@1.2.0, I kept the version there for parity.

}
}
15 changes: 12 additions & 3 deletions packages/airtable/src/airtable-loader.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Loader } from "astro/loaders";
import { AstroError } from "astro/errors";
import Airtable, { type Query, type FieldSet } from "airtable";
import { createTypeAlias, printNode, zodToTs } from "zod-to-ts";
import { zodSchemaFromAirtableTable } from "./schema.js";

export interface AirtableLoaderOptions<TFields extends FieldSet = FieldSet> {
Expand Down Expand Up @@ -44,11 +45,19 @@ export function airtableLoader({
}
logger.info(`Loaded ${records.length} records from "${table}"`);
},
schema: () =>
zodSchemaFromAirtableTable({
createSchema: async () => {
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the schema generation is async we need to use createSchema now: https://docs.astro.build/en/guides/upgrade-to/v6/#removed-schema-function-signature-content-loader-api

const schema = await zodSchemaFromAirtableTable({
baseID: base,
tableIdOrName: table,
apiKey: token,
}),
});
const identifier = "Entry";
const { node } = zodToTs(schema, identifier);
const typeAlias = createTypeAlias(node, identifier);
return {
schema,
types: `export ${printNode(typeAlias)}`,
};
},
};
}
12 changes: 6 additions & 6 deletions packages/airtable/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@ const BOOLEAN_TYPES = new Set(["checkbox", "boolean"]);
// Define schemas for complex field types
const userSchema = z.object({
id: z.string(),
email: z.string().email(),
email: z.email(),
name: z.string(),
});

const attachmentSchema = z.object({
id: z.string(),
url: z.string().url(),
url: z.url(),
filename: z.string(),
size: z.number().optional(),
type: z.string().optional(),
Expand All @@ -78,8 +78,8 @@ export const airtableTypeToZodType = (field: AirtableField): ZodTypeAny => {
.with({ type: P.when((t) => DATE_TYPES.has(t)) }, () => z.coerce.date())
.with({ type: P.when((t) => USER_TYPES.has(t)) }, () => userSchema)
.with({ type: P.when((t) => BOOLEAN_TYPES.has(t)) }, () => z.boolean())
.with({ type: "email" }, () => z.string().email())
.with({ type: "url" }, () => z.string().url())
.with({ type: "email" }, () => z.email())
.with({ type: "url" }, () => z.url())
.with(
{ type: "singleSelect", options: { choices: P.array(P.any) } },
({ options }) => {
Expand All @@ -105,7 +105,7 @@ export const airtableTypeToZodType = (field: AirtableField): ZodTypeAny => {
.with({ type: "button" }, () =>
z.object({
label: z.string(),
url: z.string().url().optional(),
url: z.url().optional(),
}),
)
.with(
Expand Down Expand Up @@ -147,7 +147,7 @@ export const airtableTypeToZodType = (field: AirtableField): ZodTypeAny => {
)
.with(
{ type: "multipleLookupValues", options: { result: { type: "object" } } },
() => z.array(z.object({}).passthrough()),
() => z.array(z.looseObject({})),
)
.with({ type: "duration" }, () => z.number())
.otherwise(() => z.unknown());
Expand Down
4 changes: 2 additions & 2 deletions packages/airtable/test/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,15 +156,15 @@ describe("Airtable to Zod Schema Mapping", () => {
it("should map email to z.string().email()", () => {
const field = airtableFieldFixtures.email;
const schema = airtableTypeToZodType(field);
expect(schema).toBeInstanceOf(z.ZodString);
expect(schema).toBeInstanceOf(z.ZodEmail);
expect(() => schema.parse("not-an-email")).toThrow();
expect(() => schema.parse("test@example.com")).not.toThrow();
});

it("should map url to z.string().url()", () => {
const field = airtableFieldFixtures.url;
const schema = airtableTypeToZodType(field);
expect(schema).toBeInstanceOf(z.ZodString);
expect(schema).toBeInstanceOf(z.ZodURL);
expect(() => schema.parse("not-a-url")).toThrow();
expect(() => schema.parse("https://example.com")).not.toThrow();
});
Expand Down
4 changes: 2 additions & 2 deletions packages/bluesky/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.17.3",
"astro": "^5.10.1",
"astro": "^6.0.8",
"publint": "^0.3.2",
"tsup": "^8.3.6",
"typescript": "^5.7.3",
"vitest": "^3.2.4"
},
"peerDependencies": {
"astro": "^4.14.0 || ^5.0.0"
"astro": "^4.14.0 || ^5.0.0 || ^6.0.0"
},
"keywords": [
"withastro",
Expand Down
4 changes: 2 additions & 2 deletions packages/csv/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
"devDependencies": {
"@arethetypeswrong/cli": "^0.17.3",
"@types/papaparse": "^5.3.15",
"astro": "^5.10.1",
"astro": "^6.0.8",
"publint": "^0.3.2",
"tsup": "^8.3.6",
"typescript": "^5.7.3"
},
"peerDependencies": {
"astro": "^4.14.0 || ^5.0.0"
"astro": "^4.14.0 || ^5.0.0 || ^6.0.0"
},
"keywords": [
"withastro",
Expand Down
8 changes: 4 additions & 4 deletions packages/feed/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.17.3",
"astro": "^5.10.1",
"astro": "^6.0.8",
"msw": "^2.10.2",
"publint": "^0.3.2",
"tsup": "^8.3.6",
"typescript": "^5.7.3"
},
"peerDependencies": {
"astro": "^4.14.0 || ^5.0.0"
"astro": "^4.14.0 || ^5.0.0 || ^6.0.0"
},
"keywords": [
"withastro",
Expand All @@ -42,7 +42,7 @@
},
"homepage": "https://github.com/ascorbic/astro-loaders",
"dependencies": {
"@rowanmanning/feed-parser": "^2.0.0",
"@ascorbic/loader-utils": "workspace:^"
"@ascorbic/loader-utils": "workspace:^",
"@rowanmanning/feed-parser": "^2.0.0"
}
}
4 changes: 2 additions & 2 deletions packages/feed/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const FeedCategorySchema = z.object({
});

// Legacy schemas from original implementation for exact backward compatibility
export const LegacyNSSchema = z.record(z.string());
export const LegacyNSSchema = z.record(z.string(), z.unknown());
Copy link
Copy Markdown
Author

@kydecker kydecker Mar 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Zod 4 requires two arguments for z.record(): https://zod.dev/v4/changelog?id=drops-single-argument-usage


export const LegacyImageSchema = z.object({
url: z.string().optional(),
Expand Down Expand Up @@ -111,7 +111,7 @@ export const LegacyItemSchema = z
enclosures: z.array(LegacyEnclosureSchema),
meta: LegacyMetaSchema,
})
.and(z.record(z.unknown())); // Allow additional fields
.and(z.record(z.string(), z.unknown())); // Allow additional fields

// Feed schema for the complete feed structure
export const FeedSchema = z.object({
Expand Down
7 changes: 4 additions & 3 deletions packages/mock/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.17.3",
"astro": "^5.10.1",
"astro": "^6.0.8",
"publint": "^0.3.2",
"tsup": "^8.3.6",
"typescript": "^5.7.3"
},
"peerDependencies": {
"astro": "^4.14.0 || ^5.0.0"
"astro": "^4.14.0 || ^5.0.0 || ^6.0.0"
},
"keywords": [
"withastro",
Expand All @@ -43,6 +43,7 @@
"dependencies": {
"@anatine/zod-mock": "^3.13.5",
"@ascorbic/loader-utils": "workspace:^",
"@faker-js/faker": "^9.4.0"
"@faker-js/faker": "^9.4.0",
"zod-to-ts": "^1.2.0"
}
}
48 changes: 29 additions & 19 deletions packages/mock/src/mock-loader.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type { Loader } from "astro/loaders";
import { AstroError } from "astro/errors";
import type { ZodSchema } from "astro/zod";
import { z } from "astro/zod";
import { generateMock } from "@anatine/zod-mock";
import { createTypeAlias, printNode, zodToTs } from "zod-to-ts";

interface SharedOptions {
/** The number of entries to generate */
Expand All @@ -17,12 +18,12 @@ interface SharedOptions {
export type MockLoaderOptions = SharedOptions &
(
| {
schema: ZodSchema;
schema: z.ZodType;
loader?: never;
}
| {
loader: Loader;
schema?: ZodSchema;
schema?: z.ZodType;
}
);
/**
Expand All @@ -33,9 +34,9 @@ export function mockLoader({
loader,
...options
}: MockLoaderOptions): Loader {
async function getSchema() {
async function getSchema(): Promise<z.ZodType<Record<string, unknown>>> {
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately had to cast getSchema() since there are conflicting types between Astro 6/Zod 4 and @anatine/zod-mock.

if (options.schema) {
return options.schema;
return options.schema as z.ZodType<Record<string, unknown>>;
}

if (!loader) {
Expand All @@ -45,30 +46,30 @@ export function mockLoader({
);
}

if (!loader.schema) {
throw new AstroError(
`The loader "${loader.name}" does not define a schema`,
"Define a schema manually and pass it to the `mockLoader`",
);
if ("createSchema" in loader && loader.createSchema) {
const { schema } = await loader.createSchema();
return schema as z.ZodType<Record<string, unknown>>;
}
if (typeof loader.schema === "function") {
return loader.schema();
} else {
return loader.schema;

if ("schema" in loader && loader.schema) {
return loader.schema as z.ZodType<Record<string, unknown>>;
}
}

const schema = getSchema();
throw new AstroError(
`The loader "${loader.name}" does not define a schema`,
"Define a schema manually and pass it to the `mockLoader`",
);
}

return {
name: "mock-loader",
load: async ({ logger, store }) => {
logger.info(
`Generating mock data${loader?.name ? ` for ${loader.name}` : ""}`,
);
const mockSchema = await schema;
const schema = await getSchema();
for (let i = 0; i < entryCount; i++) {
const data = generateMock(mockSchema, {
const data = generateMock(schema, {
seed: options.seed ? options.seed + i : undefined,
});
const id = options.idField ? data[options.idField] : i;
Expand All @@ -81,7 +82,16 @@ export function mockLoader({
}
logger.info(`Generated ${entryCount} mock entries`);
},
schema: () => schema,
createSchema: async () => {
const schema = await getSchema();
const identifier = "Entry";
const { node } = zodToTs(schema, identifier);
const typeAlias = createTypeAlias(node, identifier);
return {
schema,
types: `export ${printNode(typeAlias)}`,
};
},
};
}

Expand Down
7 changes: 3 additions & 4 deletions packages/utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.17.3",
"astro": "^5.10.1",
"astro": "^6.0.8",
"publint": "^0.3.2",
"tsup": "^8.3.6",
"typescript": "^5.7.3"
},
"peerDependencies": {
"astro": "^4.14.0 || ^5.0.0"
"astro": "^4.14.0 || ^5.0.0 || ^6.0.0"
},
"keywords": [],
"author": "",
Expand All @@ -34,6 +34,5 @@
"url": "git+https://github.com:ascorbic/astro-loaders.git",
"directory": "packages/utils"
},
"homepage": "https://github.com/ascorbic/astro-loaders",
"dependencies": {}
"homepage": "https://github.com/ascorbic/astro-loaders"
}
4 changes: 2 additions & 2 deletions packages/youtube/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.17.3",
"astro": "^5.10.1",
"astro": "^6.0.8",
"msw": "^2.10.2",
"publint": "^0.3.2",
"tsup": "^8.3.6",
"typescript": "^5.7.3"
},
"peerDependencies": {
"astro": "^4.14.0 || ^5.0.0"
"astro": "^4.14.0 || ^5.0.0 || ^6.0.0"
},
"keywords": [
"withastro",
Expand Down
Loading