diff options
Diffstat (limited to 'packages/integrations/netlify/src')
-rw-r--r-- | packages/integrations/netlify/src/index.ts | 1 | ||||
-rw-r--r-- | packages/integrations/netlify/src/integration-static.ts | 26 | ||||
-rw-r--r-- | packages/integrations/netlify/src/shared.ts | 140 |
3 files changed, 37 insertions, 130 deletions
diff --git a/packages/integrations/netlify/src/index.ts b/packages/integrations/netlify/src/index.ts index fd7fd5fed..510e560f1 100644 --- a/packages/integrations/netlify/src/index.ts +++ b/packages/integrations/netlify/src/index.ts @@ -1,2 +1,3 @@ export { netlifyEdgeFunctions } from './integration-edge-functions.js'; export { netlifyFunctions as default, netlifyFunctions } from './integration-functions.js'; +export { netlifyStatic } from './integration-static.js'; diff --git a/packages/integrations/netlify/src/integration-static.ts b/packages/integrations/netlify/src/integration-static.ts new file mode 100644 index 000000000..8814f9d2a --- /dev/null +++ b/packages/integrations/netlify/src/integration-static.ts @@ -0,0 +1,26 @@ +import type { AstroAdapter, AstroConfig, AstroIntegration, RouteData } from 'astro'; +import type { Args } from './netlify-functions.js'; +import { createRedirects } from './shared.js'; + +export function netlifyStatic(): AstroIntegration { + let _config: any; + return { + name: '@astrojs/netlify', + hooks: { + 'astro:config:setup': ({ updateConfig }) => { + updateConfig({ + build: { + // Do not output HTML redirects because we are building a `_redirects` file. + redirects: false, + }, + }); + }, + 'astro:config:done': ({ config }) => { + _config = config; + }, + 'astro:build:done': async ({ dir, routes }) => { + await createRedirects(_config, routes, dir, '', 'static'); + } + } + }; +} diff --git a/packages/integrations/netlify/src/shared.ts b/packages/integrations/netlify/src/shared.ts index 78a61a800..d452ada10 100644 --- a/packages/integrations/netlify/src/shared.ts +++ b/packages/integrations/netlify/src/shared.ts @@ -1,145 +1,25 @@ import type { AstroConfig, RouteData } from 'astro'; -import fs from 'fs'; - -type RedirectDefinition = { - dynamic: boolean; - input: string; - target: string; - weight: 0 | 1; - status: 200 | 404; -}; +import { createRedirectsFromAstroRoutes } from '@astrojs/underscore-redirects'; +import fs from 'node:fs'; export async function createRedirects( config: AstroConfig, routes: RouteData[], dir: URL, entryFile: string, - type: 'functions' | 'edge-functions' | 'builders' + type: 'functions' | 'edge-functions' | 'builders' | 'static' ) { - const _redirectsURL = new URL('./_redirects', dir); const kind = type ?? 'functions'; + const dynamicTarget = `/.netlify/${kind}/${entryFile}`; + const _redirectsURL = new URL('./_redirects', dir); - const definitions: RedirectDefinition[] = []; - - for (const route of routes) { - if (route.pathname) { - if (route.distURL) { - definitions.push({ - dynamic: false, - input: route.pathname, - target: prependForwardSlash(route.distURL.toString().replace(dir.toString(), '')), - status: 200, - weight: 1, - }); - } else { - definitions.push({ - dynamic: false, - input: route.pathname, - target: `/.netlify/${kind}/${entryFile}`, - status: 200, - weight: 1, - }); - - if (route.route === '/404') { - definitions.push({ - dynamic: true, - input: '/*', - target: `/.netlify/${kind}/${entryFile}`, - status: 404, - weight: 0, - }); - } - } - } else { - const pattern = - '/' + - route.segments - .map(([part]) => { - //(part.dynamic ? '*' : part.content) - if (part.dynamic) { - if (part.spread) { - return '*'; - } else { - return ':' + part.content; - } - } else { - return part.content; - } - }) - .join('/'); - - if (route.distURL) { - const target = - `${pattern}` + (config.build.format === 'directory' ? '/index.html' : '.html'); - definitions.push({ - dynamic: true, - input: pattern, - target, - status: 200, - weight: 1, - }); - } else { - definitions.push({ - dynamic: true, - input: pattern, - target: `/.netlify/${kind}/${entryFile}`, - status: 200, - weight: 1, - }); - } - } - } - - let _redirects = prettify(definitions); + const _redirects = createRedirectsFromAstroRoutes({ + config, routes, dir, dynamicTarget + }); + const content = _redirects.print(); // Always use appendFile() because the redirects file could already exist, // e.g. due to a `/public/_redirects` file that got copied to the output dir. // If the file does not exist yet, appendFile() automatically creates it. - await fs.promises.appendFile(_redirectsURL, _redirects, 'utf-8'); -} - -function prettify(definitions: RedirectDefinition[]) { - let minInputLength = 0, - minTargetLength = 0; - definitions.sort((a, b) => { - // Find the longest input, so we can format things nicely - if (a.input.length > minInputLength) { - minInputLength = a.input.length; - } - if (b.input.length > minInputLength) { - minInputLength = b.input.length; - } - - // Same for the target - if (a.target.length > minTargetLength) { - minTargetLength = a.target.length; - } - if (b.target.length > minTargetLength) { - minTargetLength = b.target.length; - } - - // Sort dynamic routes on top - return b.weight - a.weight; - }); - - let _redirects = ''; - // Loop over the definitions - definitions.forEach((defn, i) => { - // Figure out the number of spaces to add. We want at least 4 spaces - // after the input. This ensure that all targets line up together. - let inputSpaces = minInputLength - defn.input.length + 4; - let targetSpaces = minTargetLength - defn.target.length + 4; - _redirects += - (i === 0 ? '' : '\n') + - defn.input + - ' '.repeat(inputSpaces) + - defn.target + - ' '.repeat(Math.abs(targetSpaces)) + - defn.status; - }); - return _redirects; -} - -function prependForwardSlash(str: string) { - return str[0] === '/' ? str : '/' + str; + await fs.promises.appendFile(_redirectsURL, content, 'utf-8'); } |