Initial Commit
This commit is contained in:
14
packages/devtools/docs/sitemap/src/schemas/index.ts
Normal file
14
packages/devtools/docs/sitemap/src/schemas/index.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export {
|
||||
type ChangeFrequency,
|
||||
ChangeFrequencySchema,
|
||||
type SitemapAlternate,
|
||||
SitemapAlternateSchema,
|
||||
type SitemapImage,
|
||||
SitemapImageSchema,
|
||||
type SitemapIndex,
|
||||
SitemapIndexSchema,
|
||||
type SitemapUrl,
|
||||
SitemapUrlSchema,
|
||||
type SitemapVideo,
|
||||
SitemapVideoSchema,
|
||||
} from "./sitemap.schema";
|
||||
113
packages/devtools/docs/sitemap/src/schemas/sitemap.schema.md
Normal file
113
packages/devtools/docs/sitemap/src/schemas/sitemap.schema.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# sitemap.schema
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Defines Zod schemas for every wire-format type in `@suaveplan/sitemap`,
|
||||
providing runtime validation, static type inference, and a single source of
|
||||
truth for the shape of sitemap data structures. All schemas align with the
|
||||
sitemaps.org protocol and Google's image/video extensions.
|
||||
|
||||
## Features
|
||||
|
||||
- `ChangeFrequencySchema` — validates the seven allowed change-frequency values
|
||||
- `SitemapImageSchema` — image extension entry with optional caption, title, license, and geo-location
|
||||
- `SitemapVideoSchema` — full video extension with duration, ratings, tags, and playback metadata
|
||||
- `SitemapAlternateSchema` — hreflang alternate link pair
|
||||
- `SitemapUrlSchema` — complete URL entry composing all extensions
|
||||
- `SitemapIndexSchema` — sitemap index document with `loc` + optional `lastmod` entries
|
||||
- Inferred TypeScript types exported for each schema
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
SitemapUrlSchema,
|
||||
type SitemapUrl,
|
||||
} from "@suaveplan/sitemap";
|
||||
|
||||
const raw = {
|
||||
loc: "https://example.com/page",
|
||||
changefreq: "weekly",
|
||||
priority: 0.8,
|
||||
};
|
||||
|
||||
const url: SitemapUrl = SitemapUrlSchema.parse(raw);
|
||||
console.log(url.loc); // "https://example.com/page"
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
SitemapUrlSchema,
|
||||
SitemapImageSchema,
|
||||
SitemapVideoSchema,
|
||||
} from "@suaveplan/sitemap";
|
||||
|
||||
const richUrl = SitemapUrlSchema.parse({
|
||||
loc: "https://example.com/media",
|
||||
lastmod: "2024-06-01",
|
||||
changefreq: "daily",
|
||||
priority: 0.9,
|
||||
images: [
|
||||
SitemapImageSchema.parse({
|
||||
loc: "https://cdn.example.com/hero.jpg",
|
||||
caption: "Hero image",
|
||||
title: "Main hero",
|
||||
}),
|
||||
],
|
||||
videos: [
|
||||
SitemapVideoSchema.parse({
|
||||
thumbnailLoc: "https://cdn.example.com/thumb.jpg",
|
||||
title: "Product demo",
|
||||
description: "A walkthrough of key features",
|
||||
duration: 180,
|
||||
rating: 4.5,
|
||||
familyFriendly: true,
|
||||
tags: ["demo", "features"],
|
||||
}),
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `ChangeFrequencySchema`
|
||||
|
||||
`z.ZodEnum` — one of `"always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never"`.
|
||||
|
||||
### `SitemapImageSchema`
|
||||
|
||||
Object schema with fields: `loc` (required), `caption`, `title`, `license`, `geoLocation` (all optional strings).
|
||||
|
||||
### `SitemapVideoSchema`
|
||||
|
||||
Object schema with required fields `thumbnailLoc`, `title`, `description`; optional fields include `contentLoc`, `playerLoc`, `duration` (integer ≥ 0), `publicationDate`, `expirationDate`, `rating` (0–5), `viewCount`, `familyFriendly`, `requiresSubscription`, `live`, `tags`.
|
||||
|
||||
### `SitemapAlternateSchema`
|
||||
|
||||
Object schema with required `hreflang` and `href` string fields.
|
||||
|
||||
### `SitemapUrlSchema`
|
||||
|
||||
Object schema with required `loc`; optional `lastmod`, `changefreq`, `priority` (0–1), `images`, `videos`, `alternates`.
|
||||
|
||||
### `SitemapIndexSchema`
|
||||
|
||||
Object schema with `sitemaps` array, each entry having a required `loc` and optional `lastmod`.
|
||||
|
||||
### Inferred Types
|
||||
|
||||
- `ChangeFrequency` — union of the seven frequency strings
|
||||
- `SitemapImage` — inferred from `SitemapImageSchema`
|
||||
- `SitemapVideo` — inferred from `SitemapVideoSchema`
|
||||
- `SitemapAlternate` — inferred from `SitemapAlternateSchema`
|
||||
- `SitemapUrl` — inferred from `SitemapUrlSchema`
|
||||
- `SitemapIndex` — inferred from `SitemapIndexSchema`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
All schemas use `.min(1)` on required string fields to prevent empty-string entries from passing validation silently. Numeric ranges (`priority: 0–1`, `rating: 0–5`, `duration ≥ 0`, `viewCount ≥ 0`) are enforced at the schema level rather than in business logic, keeping validation rules co-located with type definitions. The schemas intentionally do not validate URL format — that responsibility lies with `url-utils.ts` / `SitemapBuilder`.
|
||||
90
packages/devtools/docs/sitemap/src/schemas/sitemap.schema.ts
Normal file
90
packages/devtools/docs/sitemap/src/schemas/sitemap.schema.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import z from "zod";
|
||||
|
||||
/**
|
||||
* Allowed change-frequency values per the sitemaps.org protocol.
|
||||
*/
|
||||
export const ChangeFrequencySchema = z.enum([
|
||||
"always",
|
||||
"hourly",
|
||||
"daily",
|
||||
"weekly",
|
||||
"monthly",
|
||||
"yearly",
|
||||
"never",
|
||||
]);
|
||||
|
||||
export type ChangeFrequency = z.infer<typeof ChangeFrequencySchema>;
|
||||
|
||||
/**
|
||||
* An image extension entry within a sitemap URL.
|
||||
*/
|
||||
export const SitemapImageSchema = z.object({
|
||||
loc: z.string().min(1),
|
||||
caption: z.string().optional(),
|
||||
title: z.string().optional(),
|
||||
license: z.string().optional(),
|
||||
geoLocation: z.string().optional(),
|
||||
});
|
||||
|
||||
export type SitemapImage = z.infer<typeof SitemapImageSchema>;
|
||||
|
||||
/**
|
||||
* A video extension entry within a sitemap URL.
|
||||
*/
|
||||
export const SitemapVideoSchema = z.object({
|
||||
thumbnailLoc: z.string().min(1),
|
||||
title: z.string().min(1),
|
||||
description: z.string().min(1),
|
||||
contentLoc: z.string().optional(),
|
||||
playerLoc: z.string().optional(),
|
||||
duration: z.number().int().nonnegative().optional(),
|
||||
publicationDate: z.string().optional(),
|
||||
expirationDate: z.string().optional(),
|
||||
rating: z.number().min(0).max(5).optional(),
|
||||
viewCount: z.number().int().nonnegative().optional(),
|
||||
familyFriendly: z.boolean().optional(),
|
||||
requiresSubscription: z.boolean().optional(),
|
||||
live: z.boolean().optional(),
|
||||
tags: z.array(z.string()).optional(),
|
||||
});
|
||||
|
||||
export type SitemapVideo = z.infer<typeof SitemapVideoSchema>;
|
||||
|
||||
/**
|
||||
* An hreflang alternate link annotation within a sitemap URL.
|
||||
*/
|
||||
export const SitemapAlternateSchema = z.object({
|
||||
hreflang: z.string().min(1),
|
||||
href: z.string().min(1),
|
||||
});
|
||||
|
||||
export type SitemapAlternate = z.infer<typeof SitemapAlternateSchema>;
|
||||
|
||||
/**
|
||||
* A single URL entry in a standard sitemap.
|
||||
*/
|
||||
export const SitemapUrlSchema = z.object({
|
||||
loc: z.string().min(1),
|
||||
lastmod: z.string().optional(),
|
||||
changefreq: ChangeFrequencySchema.optional(),
|
||||
priority: z.number().min(0).max(1).optional(),
|
||||
images: z.array(SitemapImageSchema).optional(),
|
||||
videos: z.array(SitemapVideoSchema).optional(),
|
||||
alternates: z.array(SitemapAlternateSchema).optional(),
|
||||
});
|
||||
|
||||
export type SitemapUrl = z.infer<typeof SitemapUrlSchema>;
|
||||
|
||||
/**
|
||||
* A sitemap index file referencing multiple child sitemaps.
|
||||
*/
|
||||
export const SitemapIndexSchema = z.object({
|
||||
sitemaps: z.array(
|
||||
z.object({
|
||||
loc: z.string().min(1),
|
||||
lastmod: z.string().optional(),
|
||||
})
|
||||
),
|
||||
});
|
||||
|
||||
export type SitemapIndex = z.infer<typeof SitemapIndexSchema>;
|
||||
Reference in New Issue
Block a user