Skip to content

Commit

Permalink
refactor: better typings (#3634)
Browse files Browse the repository at this point in the history
  • Loading branch information
alextim committed Jun 20, 2022
1 parent d9f6dcf commit facfc46
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 67 deletions.
12 changes: 6 additions & 6 deletions packages/integrations/sitemap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export default {

### entryLimit

Non-negative `Number` of entries per sitemap file. Default value is 45000. A sitemap index and multiple sitemaps are created if you have more entries. See explanation on [Google](https://developers.google.com/search/docs/advanced/sitemaps/large-sitemaps).
Non-negative `Number` of entries per sitemap file. Default value is 45000. A sitemap index and multiple sitemaps are created if you have more entries. See explanation about large sitemaps on [Google](https://developers.google.com/search/docs/advanced/sitemaps/large-sitemaps).

__astro.config.mjs__

Expand All @@ -166,7 +166,7 @@ export default {

`lastmod` - The date of page last modification.

`changefreq` and `priority` are ignored by Google.
The `changefreq` and `priority` are ignored by Google.

See detailed explanation of sitemap specific options on [sitemap.org](https://www.sitemaps.org/protocol.html).

Expand Down Expand Up @@ -194,12 +194,12 @@ export default {

Async or sync function called for each sitemap entry just before writing to a disk.

It receives as parameter `SitemapItem` object which consists of `url` (required, absolute page URL) and optional `changefreq`, `lastmod`, `priority` and `links` properties.
It receives as parameter a `SitemapItem` object which consists of `url` (required, absolute page URL) and optional `changefreq`, `lastmod` (ISO formatted date, `String` type), `priority` and `links` properties.

Optional `links` property contains a `LinkItem` list of alternate pages including a parent page.
`LinkItem` type has two required fields: `url` (the fully-qualified URL for the version of this page for the specified language) and `hreflang` (a supported language code targeted by this version of the page).
Optional `links` property contains the `LinkItem` list of alternate pages including a parent page.
The `LinkItem` type has two required fields: `url` (the fully-qualified URL for the version of this page for the specified language) and `lang` (a supported language code targeted by this version of the page).

`serialize` function should return `SitemapItem`, touched or not.
The `serialize` function should return `SitemapItem`, touched or not.

The example below shows the ability to add the sitemap specific properties individually.

Expand Down
9 changes: 0 additions & 9 deletions packages/integrations/sitemap/src/constants.ts

This file was deleted.

13 changes: 5 additions & 8 deletions packages/integrations/sitemap/src/generate-sitemap.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import { SitemapItemLoose } from 'sitemap';

import type { SitemapOptions } from './index';
import type { SitemapOptions, SitemapItem } from './index';
import { parseUrl } from './utils/parse-url';

const STATUS_CODE_PAGE_REGEXP = /\/[0-9]{3}\/?$/;

/** Construct sitemap.xml given a set of URLs */
export function generateSitemap(pages: string[], finalSiteUrl: string, opts: SitemapOptions) {
const { changefreq, priority: prioritySrc, lastmod: lastmodSrc, i18n } = opts || {};
const { changefreq, priority, lastmod: lastmodSrc, i18n } = opts!;
// TODO: find way to respect <link rel="canonical"> URLs here
const urls = [...pages].filter((url) => !STATUS_CODE_PAGE_REGEXP.test(url));
urls.sort((a, b) => a.localeCompare(b, 'en', { numeric: true })); // sort alphabetically so sitemap is same each time

const lastmod = lastmodSrc?.toISOString();
const priority = typeof prioritySrc === 'number' ? prioritySrc : undefined;

const { locales, defaultLocale } = i18n || {};
const localeCodes = Object.keys(locales || {});
Expand All @@ -27,7 +24,7 @@ export function generateSitemap(pages: string[], finalSiteUrl: string, opts: Sit
return result?.locale;
};

const urlData = urls.map((url) => {
const urlData: SitemapItem[] = urls.map((url) => {
let links;
if (defaultLocale && locales) {
const currentPath = getPath(url);
Expand All @@ -47,8 +44,8 @@ export function generateSitemap(pages: string[], finalSiteUrl: string, opts: Sit
links,
lastmod,
priority,
changefreq, // : changefreq as EnumChangefreq,
} as SitemapItemLoose;
changefreq,
};
});

return urlData;
Expand Down
9 changes: 4 additions & 5 deletions packages/integrations/sitemap/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import type { AstroConfig, AstroIntegration } from 'astro';
import { LinkItem as LinkItemBase, simpleSitemapAndIndex, SitemapItemLoose } from 'sitemap';
import { LinkItem as LinkItemBase, simpleSitemapAndIndex, SitemapItemLoose, EnumChangefreq } from 'sitemap';
import { fileURLToPath } from 'url';
import { ZodError } from 'zod';

import { changefreqValues } from './constants';
import { generateSitemap } from './generate-sitemap';
import { Logger } from './utils/logger';
import { validateOptions } from './validate-options';

export type ChangeFreq = typeof changefreqValues[number];
export type ChangeFreq = EnumChangefreq;
export type SitemapItem = Pick<
SitemapItemLoose,
'url' | 'lastmod' | 'changefreq' | 'priority' | 'links'
Expand All @@ -34,7 +33,7 @@ export type SitemapOptions =
priority?: number;

// called for each sitemap item just before to save them on disk, sync or async
serialize?(item: SitemapItemLoose): SitemapItemLoose;
serialize?(item: SitemapItem): SitemapItem | Promise<SitemapItem>;
}
| undefined;

Expand Down Expand Up @@ -103,7 +102,7 @@ const createPlugin = (options?: SitemapOptions): AstroIntegration => {

if (serialize) {
try {
const serializedUrls: SitemapItemLoose[] = [];
const serializedUrls: SitemapItem[] = [];
for (const item of urlData) {
const serialized = await Promise.resolve(serialize(item));
serializedUrls.push(serialized);
Expand Down
70 changes: 31 additions & 39 deletions packages/integrations/sitemap/src/schema.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,39 @@
import { z } from 'zod';
import { EnumChangefreq as ChangeFreq } from 'sitemap';
import { SITEMAP_CONFIG_DEFAULTS } from './config-defaults';
import { changefreqValues } from './constants';

const localeKeySchema = () => z.string().min(1);

const isFunction = (fn: any) => fn instanceof Function;

const fnSchema = () =>
z
.any()
.refine((val) => !val || isFunction(val), { message: 'Not a function' })
.optional();
const localeKeySchema = z.string().min(1);

export const SitemapOptionsSchema = z
.object({
filter: fnSchema(),
customPages: z.string().url().array().optional(),
canonicalURL: z.string().url().optional(),
.object({
filter: z.function().args(z.string()).returns(z.boolean()).optional(),
customPages: z.string().url().array().optional(),
canonicalURL: z.string().url().optional(),

i18n: z
.object({
defaultLocale: localeKeySchema(),
locales: z.record(
localeKeySchema(),
z
.string()
.min(2)
.regex(/^[a-zA-Z\-]+$/gm, {
message: 'Only English alphabet symbols and hyphen allowed',
})
),
})
.refine((val) => !val || val.locales[val.defaultLocale], {
message: '`defaultLocale` must exists in `locales` keys',
})
.optional(),
i18n: z
.object({
defaultLocale: localeKeySchema,
locales: z.record(
localeKeySchema,
z
.string()
.min(2)
.regex(/^[a-zA-Z\-]+$/gm, {
message: 'Only English alphabet symbols and hyphen allowed',
}),
),
})
.refine((val) => !val || val.locales[val.defaultLocale], {
message: '`defaultLocale` must exist in `locales` keys',
})
.optional(),

entryLimit: z.number().nonnegative().default(SITEMAP_CONFIG_DEFAULTS.entryLimit),
serialize: fnSchema(),
entryLimit: z.number().nonnegative().optional().default(SITEMAP_CONFIG_DEFAULTS.entryLimit),
serialize: z.function().args(z.any()).returns(z.any()).optional(),

changefreq: z.enum(changefreqValues).optional(),
lastmod: z.date().optional(),
priority: z.number().min(0).max(1).optional(),
})
.strict()
.default(SITEMAP_CONFIG_DEFAULTS);
changefreq: z.nativeEnum(ChangeFreq).optional(),
lastmod: z.date().optional(),
priority: z.number().min(0).max(1).optional(),
})
.strict()
.default(SITEMAP_CONFIG_DEFAULTS);

0 comments on commit facfc46

Please sign in to comment.