diff --git a/.changeset/fifty-books-jam.md b/.changeset/fifty-books-jam.md new file mode 100644 index 000000000..ab3694519 --- /dev/null +++ b/.changeset/fifty-books-jam.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fix TypeScript "types" reference in package.json diff --git a/.changeset/gentle-carrots-decide.md b/.changeset/gentle-carrots-decide.md new file mode 100644 index 000000000..604ea72f4 --- /dev/null +++ b/.changeset/gentle-carrots-decide.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Improve schema validation using zod diff --git a/examples/blog-multiple-authors/astro.config.mjs b/examples/blog-multiple-authors/astro.config.mjs index 88a052f97..68499b3fa 100644 --- a/examples/blog-multiple-authors/astro.config.mjs +++ b/examples/blog-multiple-authors/astro.config.mjs @@ -1,15 +1,13 @@ -export default { - // projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project. - // pages: './src/pages', // Path to Astro components, pages, and data - // dist: './dist', // When running `astro build`, path to final static output - // public: './public', // A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that don’t need processing. - buildOptions: { - site: 'http://example.com', // Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. - sitemap: true, // Generate sitemap (set to "false" to disable) - }, - devOptions: { - // port: 3000, // The port to run the dev server on. - // tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js' - }, +// Full Astro Configuration API Documentation: +// https://docs.astro.build/reference/configuration-reference + +// @type-check enabled! +// VSCode and other TypeScript-enabled text editors will provide auto-completion, +// helpful tooltips, and warnings if your exported object is invalid. +// You can disable this by removing "@ts-check" and `@type` comments below. + +// @ts-check +export default /** @type {import('astro').AstroUserConfig} */ ({ + // Enable the Preact renderer to support Preact JSX components. renderers: ['@astrojs/renderer-preact'], -}; +}); diff --git a/examples/blog/astro.config.mjs b/examples/blog/astro.config.mjs index 2c8e9130e..68499b3fa 100644 --- a/examples/blog/astro.config.mjs +++ b/examples/blog/astro.config.mjs @@ -1,15 +1,13 @@ -export default { - // projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project. - // pages: './src/pages', // Path to Astro components, pages, and data - // dist: './dist', // When running `astro build`, path to final static output - // public: './public', // A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that don’t need processing. - buildOptions: { - // site: 'http://example.com', // Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. - sitemap: true, // Generate sitemap (set to "false" to disable) - }, - devOptions: { - // port: 3000, // The port to run the dev server on. - // tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js' - }, +// Full Astro Configuration API Documentation: +// https://docs.astro.build/reference/configuration-reference + +// @type-check enabled! +// VSCode and other TypeScript-enabled text editors will provide auto-completion, +// helpful tooltips, and warnings if your exported object is invalid. +// You can disable this by removing "@ts-check" and `@type` comments below. + +// @ts-check +export default /** @type {import('astro').AstroUserConfig} */ ({ + // Enable the Preact renderer to support Preact JSX components. renderers: ['@astrojs/renderer-preact'], -}; +}); diff --git a/examples/docs/astro.config.mjs b/examples/docs/astro.config.mjs index 7af3aef7f..68499b3fa 100644 --- a/examples/docs/astro.config.mjs +++ b/examples/docs/astro.config.mjs @@ -1,15 +1,13 @@ -export default { - // projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project. - // pages: './src/pages', // Path to Astro components, pages, and data - // dist: './dist', // When running `astro build`, path to final static output - // public: './public', // A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that don’t need processing. - buildOptions: { - // site: 'http://example.com', // Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. - // sitemap: true, // Generate sitemap (set to "false" to disable) - }, - devOptions: { - // port: 3000, // The port to run the dev server on. - // tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js' - }, +// Full Astro Configuration API Documentation: +// https://docs.astro.build/reference/configuration-reference + +// @type-check enabled! +// VSCode and other TypeScript-enabled text editors will provide auto-completion, +// helpful tooltips, and warnings if your exported object is invalid. +// You can disable this by removing "@ts-check" and `@type` comments below. + +// @ts-check +export default /** @type {import('astro').AstroUserConfig} */ ({ + // Enable the Preact renderer to support Preact JSX components. renderers: ['@astrojs/renderer-preact'], -}; +}); diff --git a/examples/framework-lit/astro.config.mjs b/examples/framework-lit/astro.config.mjs index e4cabec8f..6a053bcc5 100644 --- a/examples/framework-lit/astro.config.mjs +++ b/examples/framework-lit/astro.config.mjs @@ -1,15 +1,13 @@ -export default { - // projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project. - // pages: './src/pages', // Path to Astro components, pages, and data - // dist: './dist', // When running `astro build`, path to final static output - // public: './public', // A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that don’t need processing. - buildOptions: { - // site: 'http://example.com', // Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. - // sitemap: true, // Generate sitemap (set to "false" to disable) - }, - devOptions: { - // port: 3000, // The port to run the dev server on. - // tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js' - }, +// Full Astro Configuration API Documentation: +// https://docs.astro.build/reference/configuration-reference + +// @type-check enabled! +// VSCode and other TypeScript-enabled text editors will provide auto-completion, +// helpful tooltips, and warnings if your exported object is invalid. +// You can disable this by removing "@ts-check" and `@type` comments below. + +// @ts-check +export default /** @type {import('astro').AstroUserConfig} */ ({ + // Enable the lit renderer to support LitHTML components and templates. renderers: ['@astrojs/renderer-lit'], -}; +}); diff --git a/examples/framework-multiple/astro.config.mjs b/examples/framework-multiple/astro.config.mjs index ee1983a24..b5fe6a073 100644 --- a/examples/framework-multiple/astro.config.mjs +++ b/examples/framework-multiple/astro.config.mjs @@ -1,15 +1,13 @@ -export default { - // projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project. - // pages: './src/pages', // Path to Astro components, pages, and data - // dist: './dist', // When running `astro build`, path to final static output - // public: './public', // A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that don’t need processing. - buildOptions: { - // site: 'http://example.com', // Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. - // sitemap: true, // Generate sitemap (set to "false" to disable) - }, - devOptions: { - // port: 3000, // The port to run the dev server on. - // tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js' - }, +// Full Astro Configuration API Documentation: +// https://docs.astro.build/reference/configuration-reference + +// @type-check enabled! +// VSCode and other TypeScript-enabled text editors will provide auto-completion, +// helpful tooltips, and warnings if your exported object is invalid. +// You can disable this by removing "@ts-check" and `@type` comments below. + +// @ts-check +export default /** @type {import('astro').AstroUserConfig} */ ({ + // Enable many renderers to support all different kinds of components. renderers: ['@astrojs/renderer-preact', '@astrojs/renderer-react', '@astrojs/renderer-svelte', '@astrojs/renderer-vue', '@astrojs/renderer-solid'], -}; +}); diff --git a/examples/framework-preact/astro.config.mjs b/examples/framework-preact/astro.config.mjs index 350d6c7de..68499b3fa 100644 --- a/examples/framework-preact/astro.config.mjs +++ b/examples/framework-preact/astro.config.mjs @@ -1,15 +1,13 @@ -export default { - // projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project. - // pages: './src/pages', // Path to Astro components, pages, and data - // dist: './dist', // When running `astro build`, path to final static output - // public: './public', // A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that don’t need processing. - buildOptions: { - // site: 'http://example.com', // Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. - // sitemap: true, // Generate sitemap (set to "false" to disable) - }, - devOptions: { - // port: 3000, // The port to run the dev server on. - // tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js' - }, +// Full Astro Configuration API Documentation: +// https://docs.astro.build/reference/configuration-reference + +// @type-check enabled! +// VSCode and other TypeScript-enabled text editors will provide auto-completion, +// helpful tooltips, and warnings if your exported object is invalid. +// You can disable this by removing "@ts-check" and `@type` comments below. + +// @ts-check +export default /** @type {import('astro').AstroUserConfig} */ ({ + // Enable the Preact renderer to support Preact JSX components. renderers: ['@astrojs/renderer-preact'], -}; +}); diff --git a/examples/framework-react/astro.config.mjs b/examples/framework-react/astro.config.mjs index da818c2be..1d13cb140 100644 --- a/examples/framework-react/astro.config.mjs +++ b/examples/framework-react/astro.config.mjs @@ -1,15 +1,13 @@ -export default { - // projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project. - // pages: './src/pages', // Path to Astro components, pages, and data - // dist: './dist', // When running `astro build`, path to final static output - // public: './public', // A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that don’t need processing. - buildOptions: { - // site: 'http://example.com', // Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. - // sitemap: true, // Generate sitemap (set to "false" to disable) - }, - devOptions: { - // port: 3000, // The port to run the dev server on. - // tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js' - }, +// Full Astro Configuration API Documentation: +// https://docs.astro.build/reference/configuration-reference + +// @type-check enabled! +// VSCode and other TypeScript-enabled text editors will provide auto-completion, +// helpful tooltips, and warnings if your exported object is invalid. +// You can disable this by removing "@ts-check" and `@type` comments below. + +// @ts-check +export default /** @type {import('astro').AstroUserConfig} */ ({ + // Enable the React renderer to support React JSX components. renderers: ['@astrojs/renderer-react'], -}; +}); diff --git a/examples/framework-solid/astro.config.mjs b/examples/framework-solid/astro.config.mjs index 59dd75f56..afb71e071 100644 --- a/examples/framework-solid/astro.config.mjs +++ b/examples/framework-solid/astro.config.mjs @@ -1,15 +1,13 @@ -export default { - // projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project. - // pages: './src/pages', // Path to Astro components, pages, and data - // dist: './dist', // When running `astro build`, path to final static output - // public: './public', // A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that don’t need processing. - buildOptions: { - // site: 'http://example.com', // Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. - // sitemap: true, // Generate sitemap (set to "false" to disable) - }, - devOptions: { - // port: 3000, // The port to run the dev server on. - // tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js' - }, +// Full Astro Configuration API Documentation: +// https://docs.astro.build/reference/configuration-reference + +// @type-check enabled! +// VSCode and other TypeScript-enabled text editors will provide auto-completion, +// helpful tooltips, and warnings if your exported object is invalid. +// You can disable this by removing "@ts-check" and `@type` comments below. + +// @ts-check +export default /** @type {import('astro').AstroUserConfig} */ ({ + // Enable the Solid renderer to support Solid JSX components. renderers: ['@astrojs/renderer-solid'], -}; +}); diff --git a/examples/framework-svelte/astro.config.mjs b/examples/framework-svelte/astro.config.mjs index 40dbab1ad..3e7d4acdb 100644 --- a/examples/framework-svelte/astro.config.mjs +++ b/examples/framework-svelte/astro.config.mjs @@ -1,15 +1,13 @@ -export default { - // projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project. - // pages: './src/pages', // Path to Astro components, pages, and data - // dist: './dist', // When running `astro build`, path to final static output - // public: './public', // A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that don’t need processing. - buildOptions: { - // site: 'http://example.com', // Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. - // sitemap: true, // Generate sitemap (set to "false" to disable) - }, - devOptions: { - // port: 3000, // The port to run the dev server on. - // tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js' - }, +// Full Astro Configuration API Documentation: +// https://docs.astro.build/reference/configuration-reference + +// @type-check enabled! +// VSCode and other TypeScript-enabled text editors will provide auto-completion, +// helpful tooltips, and warnings if your exported object is invalid. +// You can disable this by removing "@ts-check" and `@type` comments below. + +// @ts-check +export default /** @type {import('astro').AstroUserConfig} */ ({ + // Enable the Svelte renderer to support Svelte components. renderers: ['@astrojs/renderer-svelte'], -}; +}); diff --git a/examples/framework-vue/astro.config.mjs b/examples/framework-vue/astro.config.mjs index 964aa2145..c60760357 100644 --- a/examples/framework-vue/astro.config.mjs +++ b/examples/framework-vue/astro.config.mjs @@ -1,15 +1,13 @@ -export default { - // projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project. - // pages: './src/pages', // Path to Astro components, pages, and data - // dist: './dist', // When running `astro build`, path to final static output - // public: './public', // A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that don’t need processing. - buildOptions: { - // site: 'http://example.com', // Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. - // sitemap: true, // Generate sitemap (set to "false" to disable) - }, - devOptions: { - // port: 3000, // The port to run the dev server on. - // tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js' - }, +// Full Astro Configuration API Documentation: +// https://docs.astro.build/reference/configuration-reference + +// @type-check enabled! +// VSCode and other TypeScript-enabled text editors will provide auto-completion, +// helpful tooltips, and warnings if your exported object is invalid. +// You can disable this by removing "@ts-check" and `@type` comments below. + +// @ts-check +export default /** @type {import('astro').AstroUserConfig} */ ({ + // Enable the Vue renderer to support Vue components. renderers: ['@astrojs/renderer-vue'], -}; +}); diff --git a/examples/minimal/astro.config.mjs b/examples/minimal/astro.config.mjs index fcc415092..b6397b312 100644 --- a/examples/minimal/astro.config.mjs +++ b/examples/minimal/astro.config.mjs @@ -1,3 +1,13 @@ -export default { +// Full Astro Configuration API Documentation: +// https://docs.astro.build/reference/configuration-reference + +// @type-check enabled! +// VSCode and other TypeScript-enabled text editors will provide auto-completion, +// helpful tooltips, and warnings if your exported object is invalid. +// You can disable this by removing "@ts-check" and `@type` comments below. + +// @ts-check +export default /** @type {import('astro').AstroUserConfig} */ ({ + // Set "renderers" to "[]" to disable all default, builtin component support. renderers: [], -}; +}); diff --git a/examples/portfolio/astro.config.mjs b/examples/portfolio/astro.config.mjs index 350d6c7de..68499b3fa 100644 --- a/examples/portfolio/astro.config.mjs +++ b/examples/portfolio/astro.config.mjs @@ -1,15 +1,13 @@ -export default { - // projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project. - // pages: './src/pages', // Path to Astro components, pages, and data - // dist: './dist', // When running `astro build`, path to final static output - // public: './public', // A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that don’t need processing. - buildOptions: { - // site: 'http://example.com', // Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. - // sitemap: true, // Generate sitemap (set to "false" to disable) - }, - devOptions: { - // port: 3000, // The port to run the dev server on. - // tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js' - }, +// Full Astro Configuration API Documentation: +// https://docs.astro.build/reference/configuration-reference + +// @type-check enabled! +// VSCode and other TypeScript-enabled text editors will provide auto-completion, +// helpful tooltips, and warnings if your exported object is invalid. +// You can disable this by removing "@ts-check" and `@type` comments below. + +// @ts-check +export default /** @type {import('astro').AstroUserConfig} */ ({ + // Enable the Preact renderer to support Preact JSX components. renderers: ['@astrojs/renderer-preact'], -}; +}); diff --git a/examples/starter/astro.config.mjs b/examples/starter/astro.config.mjs index 706dce85b..81dadc1ea 100644 --- a/examples/starter/astro.config.mjs +++ b/examples/starter/astro.config.mjs @@ -1,14 +1,12 @@ -export default { - // projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project. - // pages: './src/pages', // Path to Astro components, pages, and data - // dist: './dist', // When running `astro build`, path to final static output - // public: './public', // A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that don’t need processing. - buildOptions: { - // site: 'http://example.com', // Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. - // sitemap: true, // Generate sitemap (set to "false" to disable) - }, - devOptions: { - // port: 3000, // The port to run the dev server on. - // tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js' - }, -}; +// Full Astro Configuration API Documentation: +// https://docs.astro.build/reference/configuration-reference + +// @type-check enabled! +// VSCode and other TypeScript-enabled text editors will provide auto-completion, +// helpful tooltips, and warnings if your exported object is invalid. +// You can disable this by removing "@ts-check" and `@type` comments below. + +// @ts-check +export default /** @type {import('astro').AstroUserConfig} */ ({ + // ... +}); diff --git a/examples/with-markdown-plugins/astro.config.mjs b/examples/with-markdown-plugins/astro.config.mjs index e02cde821..690d8f434 100644 --- a/examples/with-markdown-plugins/astro.config.mjs +++ b/examples/with-markdown-plugins/astro.config.mjs @@ -1,12 +1,14 @@ -export default { - // projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project. - // pages: './src/pages', // Path to Astro components, pages, and data - // dist: './dist', // When running `astro build`, path to final static output - // public: './public', // A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that don’t need processing. - buildOptions: { - site: 'http://example.com', // Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. - // sitemap: true, // Generate sitemap (set to "false" to disable) - }, +// Full Astro Configuration API Documentation: +// https://docs.astro.build/reference/configuration-reference + +// @type-check enabled! +// VSCode and other TypeScript-enabled text editors will provide auto-completion, +// helpful tooltips, and warnings if your exported object is invalid. +// You can disable this by removing "@ts-check" and `@type` comments below. + +// @ts-check +export default /** @type {import('astro').AstroUserConfig} */ ({ + // Enable Custom Markdown options, plugins, etc. markdownOptions: { remarkPlugins: ['remark-code-titles', 'remark-slug', ['remark-autolink-headings', { behavior: 'prepend' }]], rehypePlugins: [ @@ -14,8 +16,4 @@ export default { ['rehype-add-classes', { 'h1,h2,h3': 'title' }], ], }, - devOptions: { - // port: 3000, // The port to run the dev server on. - // tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js' - }, -}; +}); diff --git a/examples/with-nanostores/astro.config.mjs b/examples/with-nanostores/astro.config.mjs index fcabea809..b5fe6a073 100644 --- a/examples/with-nanostores/astro.config.mjs +++ b/examples/with-nanostores/astro.config.mjs @@ -1,15 +1,13 @@ -export default { - // projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project. - // pages: './src/pages', // Path to Astro components, pages, and data - // dist: './dist', // When running `astro build`, path to final static output - // public: './public', // A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that don’t need processing. - buildOptions: { - // site: 'http://example.com', // Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. - // sitemap: true, // Generate sitemap (set to "false" to disable) - }, - devOptions: { - // port: 3000, // The port to run the dev server on. - // tailwindConfig: './tailwind.config.js', // Path to tailwind.config.js if used, e.g. './tailwind.config.js' - }, - renderers: ['@astrojs/renderer-preact', '@astrojs/renderer-react', '@astrojs/renderer-svelte', '@astrojs/renderer-vue'], -}; +// Full Astro Configuration API Documentation: +// https://docs.astro.build/reference/configuration-reference + +// @type-check enabled! +// VSCode and other TypeScript-enabled text editors will provide auto-completion, +// helpful tooltips, and warnings if your exported object is invalid. +// You can disable this by removing "@ts-check" and `@type` comments below. + +// @ts-check +export default /** @type {import('astro').AstroUserConfig} */ ({ + // Enable many renderers to support all different kinds of components. + renderers: ['@astrojs/renderer-preact', '@astrojs/renderer-react', '@astrojs/renderer-svelte', '@astrojs/renderer-vue', '@astrojs/renderer-solid'], +}); diff --git a/examples/with-tailwindcss/astro.config.mjs b/examples/with-tailwindcss/astro.config.mjs index f93e801ce..e94cfab62 100644 --- a/examples/with-tailwindcss/astro.config.mjs +++ b/examples/with-tailwindcss/astro.config.mjs @@ -1,15 +1,17 @@ -export default { - // projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project. - // pages: './src/pages', // Path to Astro components, pages, and data - // dist: './dist', // When running `astro build`, path to final static output - // public: './public', // A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that don’t need processing. - buildOptions: { - // site: 'http://example.com', // Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. - sitemap: true, // Generate sitemap (set to "false" to disable) - }, +// Full Astro Configuration API Documentation: +// https://docs.astro.build/reference/configuration-reference + +// @type-check enabled! +// VSCode and other TypeScript-enabled text editors will provide auto-completion, +// helpful tooltips, and warnings if your exported object is invalid. +// You can disable this by removing "@ts-check" and `@type` comments below. + +// @ts-check +export default /** @type {import('astro').AstroUserConfig} */ ({ + // Enable Tailwind by telling Astro where your Tailwind config file lives. devOptions: { - // port: 3000, // The port to run the dev server on. - tailwindConfig: './tailwind.config.js', // Path to tailwind.config.js if used, e.g. './tailwind.config.js' + tailwindConfig: './tailwind.config.js', }, + // Enable the Preact renderer to support Preact JSX components. renderers: ['@astrojs/renderer-preact'], -}; +}); diff --git a/packages/astro/package.json b/packages/astro/package.json index 1fca0a9fc..9e979d65b 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -4,7 +4,7 @@ "author": "Skypack", "license": "MIT", "type": "module", - "types": "./dist/types", + "types": "./dist/types/@types/public.d.ts", "repository": { "type": "git", "url": "https://github.com/snowpackjs/astro.git", @@ -97,7 +97,8 @@ "supports-esm": "^1.0.0", "tiny-glob": "^0.2.8", "unified": "^9.2.1", - "yargs-parser": "^20.2.7" + "yargs-parser": "^20.2.7", + "zod": "^3.8.1" }, "devDependencies": { "@babel/types": "^7.14.0", diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index bd9986a1f..88aabeff4 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -1,7 +1,7 @@ import type { ImportSpecifier, ImportDefaultSpecifier, ImportNamespaceSpecifier } from '@babel/types'; -import type { AstroMarkdownOptions } from '@astrojs/markdown-support'; -import type { AstroConfig } from './config'; +import type { AstroUserConfig, AstroConfig } from './config'; +export { AstroUserConfig, AstroConfig }; export interface RouteData { type: 'page'; pattern: RegExp; @@ -14,28 +14,7 @@ export interface RouteData { export interface ManifestData { routes: RouteData[]; } -export interface AstroConfigRaw { - dist: string; - projectRoot: string; - src: string; - pages: string; - public: string; - jsx?: string; -} -export { AstroMarkdownOptions, AstroConfig }; - -export type AstroUserConfig = Omit & { - buildOptions: { - sitemap: boolean; - }; - devOptions: { - hostname?: string; - port?: number; - projectRoot?: string; - tailwindConfig?: string; - }; -}; export interface JsxItem { name: string; diff --git a/packages/astro/src/@types/config.ts b/packages/astro/src/@types/config.ts index a3699ad04..585f4687b 100644 --- a/packages/astro/src/@types/config.ts +++ b/packages/astro/src/@types/config.ts @@ -1,32 +1,39 @@ import type { AstroMarkdownOptions } from '@astrojs/markdown-support'; -export interface AstroConfig { +import type { AstroConfigSchema } from '../config'; +import type { z } from 'zod'; + +/** + * The Astro User Config Format: + * This is the type interface for your astro.config.mjs default export. + */ +export interface AstroUserConfig { /** * Where to resolve all URLs relative to. Useful if you have a monorepo project. * Default: '.' (current working directory) */ - projectRoot: URL; + projectRoot?: string; /** * Path to the `astro build` output. * Default: './dist' */ - dist: string; + dist?: string; /** * Path to all of your Astro components, pages, and data. * Default: './src' */ - src: URL; + src?: string; /** * Path to your Astro/Markdown pages. Each file in this directory * becomes a page in your final build. * Default: './src/pages' */ - pages: URL; + pages?: string; /** * Path to your public files. These are copied over into your build directory, untouched. * Useful for favicons, images, and other files that don't need processing. * Default: './public' */ - public: URL; + public?: string; /** * Framework component renderers enable UI framework rendering (static and dynamic). * When you define this in your configuration, all other defaults are disabled. @@ -41,26 +48,26 @@ export interface AstroConfig { /** Options for rendering markdown content */ markdownOptions?: Partial; /** Options specific to `astro build` */ - buildOptions: { + buildOptions?: { /** Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. */ site?: string; /** Generate an automatically-generated sitemap for your build. * Default: true */ - sitemap: boolean; + sitemap?: boolean; /** - * Control the output file/URL format of each page. - * If true, Astro will generate a directory with a nested index.html (ex: "/foo/index.html") for each page. - * If false, Astro will generate a matching HTML file (ex: "/foo.html") instead of a directory. - * Default: true + * Control the output file URL format of each page. + * If 'file', Astro will generate a matching HTML file (ex: "/foo.html") instead of a directory. + * If 'directory', Astro will generate a directory with a nested index.html (ex: "/foo/index.html") for each page. + * Default: 'directory' */ - pageDirectoryUrl: boolean; + pageUrlFormat?: 'file' | 'directory'; }; /** Options for the development server run with `astro dev`. */ - devOptions: { + devOptions?: { hostname?: string; /** The port to run the dev server on. */ - port: number; + port?: number; /** Path to tailwind.config.js, if used */ tailwindConfig?: string; /** @@ -70,6 +77,20 @@ export interface AstroConfig { * 'ignore' - Match URLs regardless of whether a trailing "/" exists * Default: 'always' */ - trailingSlash: 'always' | 'never' | 'ignore'; + trailingSlash?: 'always' | 'never' | 'ignore'; }; } + + +// NOTE(fks): We choose to keep our hand-generated AstroUserConfig interface so that +// we can add JSDoc-style documentation and link to the definition file in our repo. +// However, Zod comes with the ability to auto-generate AstroConfig from the schema +// above. If we ever get to the point where we no longer need the dedicated +// @types/config.ts file, consider replacing it with the following lines: +// +// export interface AstroUserConfig extends z.input { +// markdownOptions?: Partial; +// } +export interface AstroConfig extends z.output { + markdownOptions: Partial; +} \ No newline at end of file diff --git a/packages/astro/src/@types/public.ts b/packages/astro/src/@types/public.ts new file mode 100644 index 000000000..dbce2fee4 --- /dev/null +++ b/packages/astro/src/@types/public.ts @@ -0,0 +1 @@ +export {AstroConfig, AstroUserConfig} from './config'; \ No newline at end of file diff --git a/packages/astro/src/build.ts b/packages/astro/src/build.ts index 5fc32ec2e..6f60c862a 100644 --- a/packages/astro/src/build.ts +++ b/packages/astro/src/build.ts @@ -32,7 +32,6 @@ function isRemoteOrEmbedded(url: string) { /** The primary build action */ export async function build(astroConfig: AstroConfig, logging: LogOptions = defaultLogging): Promise<0 | 1> { const { projectRoot } = astroConfig; - const dist = new URL(astroConfig.dist + '/', projectRoot); const buildState: BuildOutput = {}; const depTree: BundleMap = {}; const timer: Record = {}; @@ -54,7 +53,7 @@ export async function build(astroConfig: AstroConfig, logging: LogOptions = defa try { // 0. erase build directory - await del(fileURLToPath(dist)); + await del(fileURLToPath(astroConfig.dist)); /** * 1. Build Pages @@ -197,7 +196,7 @@ ${stack} timer.sitemap = performance.now(); info(logging, 'build', yellow('! creating sitemap...')); const sitemap = generateSitemap(buildState, astroConfig.buildOptions.site); - const sitemapPath = new URL('sitemap.xml', dist); + const sitemapPath = new URL('sitemap.xml', astroConfig.dist); await fs.promises.mkdir(path.dirname(fileURLToPath(sitemapPath)), { recursive: true }); await fs.promises.writeFile(sitemapPath, sitemap, 'utf8'); info(logging, 'build', green('✔'), 'sitemap built.'); @@ -208,7 +207,7 @@ ${stack} timer.write = performance.now(); await Promise.all( Object.keys(buildState).map(async (id) => { - const outPath = new URL(`.${id}`, dist); + const outPath = new URL(`.${id}`, astroConfig.dist); const parentDir = path.dirname(fileURLToPath(outPath)); await fs.promises.mkdir(parentDir, { recursive: true }); await fs.promises.writeFile(outPath, buildState[id].contents, buildState[id].encoding); @@ -229,7 +228,7 @@ ${stack} await Promise.all( publicFiles.map(async (filepath) => { const srcPath = new URL(filepath, astroConfig.public); - const distPath = new URL(filepath, dist); + const distPath = new URL(filepath, astroConfig.dist); await fs.promises.mkdir(path.dirname(fileURLToPath(distPath)), { recursive: true }); await fs.promises.copyFile(srcPath, distPath); }) @@ -249,7 +248,7 @@ ${stack} info(logging, 'build', yellow(`! bundling...`)); if (jsImports.size > 0) { timer.bundleJS = performance.now(); - const jsStats = await bundleJS(jsImports, { dist: new URL(dist + '/', projectRoot), astroRuntime }); + const jsStats = await bundleJS(jsImports, { dist: astroConfig.dist, astroRuntime }); mapBundleStatsToURLStats({ urlStats, depTree, bundleStats: jsStats }); debug(logging, 'build', `bundled JS [${stopTimer(timer.bundleJS)}]`); info(logging, 'build', green(`✔`), 'bundling complete.'); diff --git a/packages/astro/src/build/page.ts b/packages/astro/src/build/page.ts index fed683949..6708d55c0 100644 --- a/packages/astro/src/build/page.ts +++ b/packages/astro/src/build/page.ts @@ -45,14 +45,14 @@ export async function getStaticPathsForPage({ }; } -function formatOutFile(path: string, pageDirectoryUrl: boolean) { +function formatOutFile(path: string, pageUrlFormat: AstroConfig['buildOptions']['pageUrlFormat']) { if (path === '/404') { return '/404.html'; } if (path === '/') { return '/index.html'; } - if (pageDirectoryUrl) { + if (pageUrlFormat === 'directory') { return _path.posix.join(path, '/index.html'); } return `${path}.html`; @@ -68,7 +68,7 @@ export async function buildStaticPage({ astroConfig, buildState, path, route, as err.filename = fileURLToPath(location.fileURL); throw err; } - buildState[formatOutFile(path, astroConfig.buildOptions.pageDirectoryUrl)] = { + buildState[formatOutFile(path, astroConfig.buildOptions.pageUrlFormat)] = { srcPath: location.fileURL, contents: result.contents, contentType: 'text/html', diff --git a/packages/astro/src/compiler/codegen/index.ts b/packages/astro/src/compiler/codegen/index.ts index 09bd95b46..8fcf50768 100644 --- a/packages/astro/src/compiler/codegen/index.ts +++ b/packages/astro/src/compiler/codegen/index.ts @@ -1,6 +1,6 @@ import type { Ast, Script, Style, TemplateNode, Expression } from '@astrojs/parser'; import type { CompileOptions } from '../../@types/compiler'; -import type { AstroConfig, AstroMarkdownOptions, TransformResult, ComponentInfo, Components } from '../../@types/astro'; +import type { AstroConfig, TransformResult, ComponentInfo, Components } from '../../@types/astro'; import type { ImportDeclaration, ExportNamedDeclaration, VariableDeclarator, Identifier, ImportDefaultSpecifier } from '@babel/types'; import type { Attribute } from './interfaces'; import eslexer from 'es-module-lexer'; @@ -566,7 +566,7 @@ async function compileHtml(enterNode: TemplateNode, state: CodegenState, compile } const { $scope: scopedClassName } = state.markers.insideMarkdown as Record<'$scope', any>; let { content: rendered } = await renderMarkdown(dedent(md), { - ...(markdownOptions as AstroMarkdownOptions), + ...markdownOptions, $: { scopedClassName: scopedClassName && scopedClassName.slice(1, -1) }, }); diff --git a/packages/astro/src/config.ts b/packages/astro/src/config.ts index 11e28b168..3e20559f8 100644 --- a/packages/astro/src/config.ts +++ b/packages/astro/src/config.ts @@ -1,108 +1,114 @@ -import type { AstroConfig } from './@types/astro'; -import path from 'path'; import { existsSync } from 'fs'; import getPort from 'get-port'; +import path from 'path'; +import { z } from 'zod'; +import { AstroConfig, AstroUserConfig } from './@types/astro'; +import { addTrailingSlash } from './util.js'; -/** Type util */ -const type = (thing: any): string => (Array.isArray(thing) ? 'Array' : typeof thing); - -/** Throws error if a user provided an invalid config. Manually-implemented to avoid a heavy validation library. */ -function validateConfig(config: any): void { - // basic - if (config === undefined || config === null) throw new Error(`[config] Config empty!`); - if (typeof config !== 'object') throw new Error(`[config] Expected object, received ${typeof config}`); - - // strings - for (const key of ['projectRoot', 'pages', 'dist', 'public']) { - if (config[key] !== undefined && config[key] !== null && typeof config[key] !== 'string') { - throw new Error(`[config] ${key}: ${JSON.stringify(config[key])}\n Expected string, received ${type(config[key])}.`); - } - } - - // booleans - for (const key of ['sitemap']) { - if (config[key] !== undefined && config[key] !== null && typeof config[key] !== 'boolean') { - throw new Error(`[config] ${key}: ${JSON.stringify(config[key])}\n Expected boolean, received ${type(config[key])}.`); - } - } - - // buildOptions - if (config.buildOptions) { - // buildOptions.site - if (config.buildOptions.site !== undefined) { - if (typeof config.buildOptions.site !== 'string') throw new Error(`[config] buildOptions.site is not a string`); - try { - new URL(config.buildOptions.site); - } catch (err) { - throw new Error('[config] buildOptions.site must be a valid URL'); - } - } - } - - // devOptions - if (typeof config.devOptions?.port !== 'number') { - throw new Error(`[config] devOptions.port: Expected number, received ${type(config.devOptions?.port)}`); - } - if (typeof config.devOptions?.hostname !== 'string') { - throw new Error(`[config] devOptions.hostname: Expected string, received ${type(config.devOptions?.hostname)}`); - } - if (config.devOptions?.tailwindConfig !== undefined && typeof config.devOptions?.tailwindConfig !== 'string') { - throw new Error(`[config] devOptions.tailwindConfig: Expected string, received ${type(config.devOptions?.tailwindConfig)}`); - } -} - -/** Set default config values */ -async function configDefaults(userConfig?: any): Promise { - const config: any = { ...(userConfig || {}) }; - - if (config.projectRoot === undefined) config.projectRoot = '.'; - if (config.src === undefined) config.src = './src'; - if (config.pages === undefined) config.pages = './src/pages'; - if (config.dist === undefined) config.dist = './dist'; - if (config.public === undefined) config.public = './public'; - if (config.devOptions === undefined) config.devOptions = {}; - if (config.devOptions.port === undefined) config.devOptions.port = await getPort({ port: getPort.makeRange(3000, 3050) }); - if (config.devOptions.hostname === undefined) config.devOptions.hostname = 'localhost'; - if (config.devOptions.trailingSlash === undefined) config.devOptions.trailingSlash = 'ignore'; - if (config.buildOptions === undefined) config.buildOptions = {}; - if (config.buildOptions.pageDirectoryUrl === undefined) config.buildOptions.pageDirectoryUrl = true; - if (config.markdownOptions === undefined) config.markdownOptions = {}; - if (config.buildOptions.sitemap === undefined) config.buildOptions.sitemap = true; - - return config; -} +export const AstroConfigSchema = z.object({ + projectRoot: z + .string() + .optional() + .default('.') + .transform((val) => new URL(val)), + src: z + .string() + .optional() + .default('./src') + .transform((val) => new URL(val)), + pages: z + .string() + .optional() + .default('./src/pages') + .transform((val) => new URL(val)), + public: z + .string() + .optional() + .default('./public') + .transform((val) => new URL(val)), + dist: z + .string() + .optional() + .default('./dist') + .transform((val) => new URL(val)), + renderers: z.array(z.string()).optional().default(['@astrojs/renderer-svelte', '@astrojs/renderer-vue', '@astrojs/renderer-react', '@astrojs/renderer-preact']), + markdownOptions: z + .object({ + footnotes: z.boolean().optional(), + gfm: z.boolean().optional(), + remarkPlugins: z.array(z.any()).optional(), + rehypePlugins: z.array(z.any()).optional(), + }) + .optional() + .default({}), + buildOptions: z + .object({ + site: z.string().optional(), + sitemap: z.boolean().optional().default(true), + pageUrlFormat: z + .union([z.literal('file'), z.literal('directory')]) + .optional() + .default('directory'), + }) + .optional() + .default({}), + devOptions: z + .object({ + hostname: z.string().optional().default('localhost'), + port: z + .number() + .optional() + .transform((val) => val || getPort({ port: getPort.makeRange(3000, 3050) })), + tailwindConfig: z.string().optional(), + trailingSlash: z + .union([z.literal('always'), z.literal('never'), z.literal('ignore')]) + .optional() + .default('ignore'), + }) + .optional() + .default({}), +}); /** Turn raw config values into normalized values */ -function normalizeConfig(userConfig: any, root: string): AstroConfig { - const config: any = { ...(userConfig || {}) }; - +async function validateConfig(userConfig: any, root: string): Promise { const fileProtocolRoot = `file://${root}/`; - config.projectRoot = new URL(config.projectRoot + '/', fileProtocolRoot); - config.src = new URL(config.src + '/', fileProtocolRoot); - config.pages = new URL(config.pages + '/', fileProtocolRoot); - config.public = new URL(config.public + '/', fileProtocolRoot); - - return config as AstroConfig; + // We need to extend the global schema to add transforms that are relative to root. + // This is type checked against the global schema to make sure we still match. + const AstroConfigRelativeSchema = AstroConfigSchema.extend({ + projectRoot: z + .string() + .default('.') + .transform((val) => new URL(addTrailingSlash(val), fileProtocolRoot)), + src: z + .string() + .default('./src') + .transform((val) => new URL(addTrailingSlash(val), fileProtocolRoot)), + pages: z + .string() + .default('./src/pages') + .transform((val) => new URL(addTrailingSlash(val), fileProtocolRoot)), + public: z + .string() + .default('./public') + .transform((val) => new URL(addTrailingSlash(val), fileProtocolRoot)), + dist: z + .string() + .default('./dist') + .transform((val) => new URL(addTrailingSlash(val), fileProtocolRoot)), + }); + return AstroConfigRelativeSchema.parseAsync(userConfig); } /** Attempt to load an `astro.config.mjs` file */ export async function loadConfig(rawRoot: string | undefined, configFileName = 'astro.config.mjs'): Promise { const root = rawRoot ? path.resolve(rawRoot) : process.cwd(); const astroConfigPath = new URL(`./${configFileName}`, `file://${root}/`); - - // load - let config: any; + let userConfig: AstroUserConfig = {}; + // Load a user-config, if one exists and is provided if (existsSync(astroConfigPath)) { - config = await configDefaults((await import(astroConfigPath.href)).default); - } else { - config = await configDefaults(); + userConfig = (await import(astroConfigPath.href)).default; } - - // validate - validateConfig(config); - - // normalize - config = normalizeConfig(config, root); - - return config as AstroConfig; + // normalize, validate, and return + const config = await validateConfig(userConfig, root); + return config; } diff --git a/packages/astro/src/runtime.ts b/packages/astro/src/runtime.ts index e585511d2..cf69b4aa1 100644 --- a/packages/astro/src/runtime.ts +++ b/packages/astro/src/runtime.ts @@ -351,7 +351,7 @@ async function createSnowpack(astroConfig: AstroConfig, options: CreateSnowpackO }, buildOptions: { baseUrl: astroConfig.buildOptions.site || '/', // note: Snowpack needs this fallback - out: astroConfig.dist, + out: fileURLToPath(astroConfig.dist), }, packageOptions: { knownEntrypoints, diff --git a/packages/astro/src/util.ts b/packages/astro/src/util.ts index 249f7eb43..92f59acdd 100644 --- a/packages/astro/src/util.ts +++ b/packages/astro/src/util.ts @@ -43,3 +43,14 @@ export function validateGetStaticPathsResult(result: GetStaticPathsResult, loggi } }); } + + +/** Add / to beginning of string (but don’t double-up) */ +export function addLeadingSlash(path: string) { + return path.replace(/^\/?/, '/'); +} + +/** Add / to the end of string (but don’t double-up) */ +export function addTrailingSlash(path: string) { + return path.replace(/\/?$/, '/'); +} \ No newline at end of file diff --git a/packages/astro/test/astro-pageDirectoryUrl.test.js b/packages/astro/test/astro-pageDirectoryUrl.test.js index 0dde1286f..dc11f0670 100644 --- a/packages/astro/test/astro-pageDirectoryUrl.test.js +++ b/packages/astro/test/astro-pageDirectoryUrl.test.js @@ -2,7 +2,7 @@ import { suite } from 'uvu'; import * as assert from 'uvu/assert'; import { setupBuild } from './helpers.js'; -const PageDirectoryUrl = suite('pageDirectoryUrl'); +const PageDirectoryUrl = suite('pageUrlFormat'); setupBuild(PageDirectoryUrl, './fixtures/astro-page-directory-url'); diff --git a/packages/astro/test/fixtures/astro-page-directory-url/astro.config.mjs b/packages/astro/test/fixtures/astro-page-directory-url/astro.config.mjs index 995a3dc46..309bb9d5a 100644 --- a/packages/astro/test/fixtures/astro-page-directory-url/astro.config.mjs +++ b/packages/astro/test/fixtures/astro-page-directory-url/astro.config.mjs @@ -1,5 +1,5 @@ export default { buildOptions: { - pageDirectoryUrl: false + pageUrlFormat: 'file' } }; diff --git a/packages/astro/test/helpers.js b/packages/astro/test/helpers.js index 411cd7677..e579c5ed3 100644 --- a/packages/astro/test/helpers.js +++ b/packages/astro/test/helpers.js @@ -85,7 +85,7 @@ export function setupBuild(Suite, fixturePath) { context.build = () => astroBuild(astroConfig, { level: 'error' }); context.readFile = async (path) => { - const resolved = fileURLToPath(new URL(`${fixturePath}/${astroConfig.dist}${path}`, import.meta.url)); + const resolved = fileURLToPath(new URL(path.replace(/^\//, ''), astroConfig.dist)); return readFileSync(resolved, { encoding: 'utf8' }); }; diff --git a/yarn.lock b/yarn.lock index 186782397..6318e09bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10989,6 +10989,11 @@ zepto@^1.2.0: resolved "https://registry.yarnpkg.com/zepto/-/zepto-1.2.0.tgz#e127bd9e66fd846be5eab48c1394882f7c0e4f98" integrity sha1-4Se9nmb9hGvl6rSME5SIL3wOT5g= +zod@^3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.8.1.tgz#b1173c3b4ac2a9e06d302ff580e3b41902766b9f" + integrity sha512-u4Uodl7dLh8nXZwqXL1SM5FAl5b4lXYHOxMUVb9lqhlEAZhA2znX+0oW480m0emGFMxpoRHzUncAqRkc4h8ZJA== + zwitch@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920"