summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Matthew Phillips <matthew@skypack.dev> 2022-04-06 16:21:46 -0400
committerGravatar GitHub <noreply@github.com> 2022-04-06 16:21:46 -0400
commitc6f8bce7c35cc4fd450fe1b6cc8297a81e413b8e (patch)
treefbfd7b639a4502ecd51de388721217306618b4b9
parent8bd49c95365f7bbce41e19b7e8658ad639c22f31 (diff)
downloadastro-c6f8bce7c35cc4fd450fe1b6cc8297a81e413b8e.tar.gz
astro-c6f8bce7c35cc4fd450fe1b6cc8297a81e413b8e.tar.zst
astro-c6f8bce7c35cc4fd450fe1b6cc8297a81e413b8e.zip
Fix Netlify adapter and dynamic routes (#3011)
* Fix Netlify adapter and dynamic routes * Changeset
-rw-r--r--.changeset/nervous-chairs-check.md6
-rw-r--r--package.json2
-rw-r--r--packages/astro/src/@types/astro.ts7
-rw-r--r--packages/astro/src/core/routing/manifest/create.ts19
-rw-r--r--packages/astro/src/core/routing/manifest/serialization.ts10
-rw-r--r--packages/integrations/netlify/package.json3
-rw-r--r--packages/integrations/netlify/src/index.ts4
-rw-r--r--packages/integrations/netlify/test/dynamic-route.test.js37
-rw-r--r--packages/integrations/netlify/test/fixtures/.gitignore1
-rw-r--r--packages/integrations/netlify/test/fixtures/dynamic-route/src/pages/products/[id].astro11
10 files changed, 82 insertions, 18 deletions
diff --git a/.changeset/nervous-chairs-check.md b/.changeset/nervous-chairs-check.md
new file mode 100644
index 000000000..bce6918fc
--- /dev/null
+++ b/.changeset/nervous-chairs-check.md
@@ -0,0 +1,6 @@
+---
+'astro': patch
+'@astrojs/netlify': patch
+---
+
+Fixes dynamic routes in the Netlify adapter
diff --git a/package.json b/package.json
index 9883dfd85..65399af15 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,7 @@
"build:ci": "turbo run build:ci --no-deps --scope=astro --scope=create-astro --scope=\"@astrojs/*\"",
"build:examples": "turbo run build --scope=\"@example/*\"",
"dev": "turbo run dev --no-deps --no-cache --parallel --scope=astro --scope=create-astro --scope=\"@astrojs/*\"",
- "test": "pnpm run test --filter astro --filter @astrojs/webapi --filter @astrojs/deno",
+ "test": "pnpm run test --filter astro --filter @astrojs/webapi --filter @astrojs/deno --filter @astrojs/netlify",
"test:match": "cd packages/astro && pnpm run test:match",
"test:templates": "pnpm run test --filter create-astro",
"test:smoke": "node scripts/smoke/index.js",
diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts
index b0563d9aa..76e24a4a0 100644
--- a/packages/astro/src/@types/astro.ts
+++ b/packages/astro/src/@types/astro.ts
@@ -798,12 +798,19 @@ export interface AstroIntegration {
export type RouteType = 'page' | 'endpoint';
+export interface RoutePart {
+ content: string;
+ dynamic: boolean;
+ spread: boolean;
+}
+
export interface RouteData {
component: string;
generate: (data?: any) => string;
params: string[];
pathname?: string;
pattern: RegExp;
+ segments: RoutePart[][];
type: RouteType;
}
diff --git a/packages/astro/src/core/routing/manifest/create.ts b/packages/astro/src/core/routing/manifest/create.ts
index ec1d6a578..9555d9753 100644
--- a/packages/astro/src/core/routing/manifest/create.ts
+++ b/packages/astro/src/core/routing/manifest/create.ts
@@ -1,4 +1,4 @@
-import type { AstroConfig, ManifestData, RouteData } from '../../../@types/astro';
+import type { AstroConfig, ManifestData, RouteData, RoutePart } from '../../../@types/astro';
import type { LogOptions } from '../../logger/core';
import fs from 'fs';
@@ -9,16 +9,10 @@ import { fileURLToPath } from 'url';
import { warn } from '../../logger/core.js';
import { resolvePages } from '../../util.js';
-interface Part {
- content: string;
- dynamic: boolean;
- spread: boolean;
-}
-
interface Item {
basename: string;
ext: string;
- parts: Part[];
+ parts: RoutePart[];
file: string;
isDir: boolean;
isIndex: boolean;
@@ -35,7 +29,7 @@ function countOccurrences(needle: string, haystack: string) {
}
function getParts(part: string, file: string) {
- const result: Part[] = [];
+ const result: RoutePart[] = [];
part.split(/\[(.+?\(.+?\)|.+?)\]/).map((str, i) => {
if (!str) return;
const dynamic = i % 2 === 1;
@@ -56,7 +50,7 @@ function getParts(part: string, file: string) {
return result;
}
-function getPattern(segments: Part[][], addTrailingSlash: AstroConfig['trailingSlash']) {
+function getPattern(segments: RoutePart[][], addTrailingSlash: AstroConfig['trailingSlash']) {
const pathname = segments
.map((segment) => {
return segment[0].spread
@@ -94,7 +88,7 @@ function getTrailingSlashPattern(addTrailingSlash: AstroConfig['trailingSlash'])
return '\\/?$';
}
-function getGenerator(segments: Part[][], addTrailingSlash: AstroConfig['trailingSlash']) {
+function getGenerator(segments: RoutePart[][], addTrailingSlash: AstroConfig['trailingSlash']) {
const template = segments
.map((segment) => {
return segment[0].spread
@@ -181,7 +175,7 @@ export function createRouteManifest(
const validPageExtensions: Set<string> = new Set(['.astro', '.md']);
const validEndpointExtensions: Set<string> = new Set(['.js', '.ts']);
- function walk(dir: string, parentSegments: Part[][], parentParams: string[]) {
+ function walk(dir: string, parentSegments: RoutePart[][], parentParams: string[]) {
let items: Item[] = [];
fs.readdirSync(dir).forEach((basename) => {
const resolved = path.join(dir, basename);
@@ -285,6 +279,7 @@ export function createRouteManifest(
routes.push({
type: item.isPage ? 'page' : 'endpoint',
pattern,
+ segments,
params,
component,
generate,
diff --git a/packages/astro/src/core/routing/manifest/serialization.ts b/packages/astro/src/core/routing/manifest/serialization.ts
index e167eb374..fcd932738 100644
--- a/packages/astro/src/core/routing/manifest/serialization.ts
+++ b/packages/astro/src/core/routing/manifest/serialization.ts
@@ -1,11 +1,12 @@
-import type { RouteData, SerializedRouteData } from '../../../@types/astro';
+import type { RouteData, SerializedRouteData, RoutePart } from '../../../@types/astro';
function createRouteData(
pattern: RegExp,
params: string[],
component: string,
pathname: string | undefined,
- type: 'page' | 'endpoint'
+ type: 'page' | 'endpoint',
+ segments: RoutePart[][]
): RouteData {
return {
type,
@@ -15,6 +16,7 @@ function createRouteData(
// TODO bring back
generate: () => '',
pathname: pathname || undefined,
+ segments
};
}
@@ -26,7 +28,7 @@ export function serializeRouteData(routeData: RouteData): SerializedRouteData {
}
export function deserializeRouteData(rawRouteData: SerializedRouteData) {
- const { component, params, pathname, type } = rawRouteData;
+ const { component, params, pathname, type, segments } = rawRouteData;
const pattern = new RegExp(rawRouteData.pattern);
- return createRouteData(pattern, params, component, pathname, type);
+ return createRouteData(pattern, params, component, pathname, type, segments);
}
diff --git a/packages/integrations/netlify/package.json b/packages/integrations/netlify/package.json
index 4402076c1..ed3d1ff36 100644
--- a/packages/integrations/netlify/package.json
+++ b/packages/integrations/netlify/package.json
@@ -21,7 +21,8 @@
},
"scripts": {
"build": "astro-scripts build \"src/**/*.ts\" && tsc",
- "dev": "astro-scripts dev \"src/**/*.ts\""
+ "dev": "astro-scripts dev \"src/**/*.ts\"",
+ "test": "mocha --exit --timeout 20000"
},
"dependencies": {
"@astrojs/webapi": "^0.11.0"
diff --git a/packages/integrations/netlify/src/index.ts b/packages/integrations/netlify/src/index.ts
index 181303e33..aa1b5d33c 100644
--- a/packages/integrations/netlify/src/index.ts
+++ b/packages/integrations/netlify/src/index.ts
@@ -53,6 +53,10 @@ function netlifyFunctions({ dist }: NetlifyFunctionsOptions = {}): AstroIntegrat
if (route.pathname) {
_redirects += `
${route.pathname} /.netlify/functions/${entryFile} 200`;
+ } else {
+ const pattern = '/' + route.segments.map(([part]) => part.dynamic ? '*' : part.content).join('/');
+ _redirects += `
+${pattern} /.netlify/functions/${entryFile} 200`;
}
}
diff --git a/packages/integrations/netlify/test/dynamic-route.test.js b/packages/integrations/netlify/test/dynamic-route.test.js
new file mode 100644
index 000000000..bc9335bfe
--- /dev/null
+++ b/packages/integrations/netlify/test/dynamic-route.test.js
@@ -0,0 +1,37 @@
+import { expect } from 'chai';
+import { load as cheerioLoad } from 'cheerio';
+import { loadFixture } from '../../../astro/test/test-utils.js';
+import netlifyAdapter from '../dist/index.js';
+import { fileURLToPath } from 'url';
+
+// Asset bundling
+describe('Dynamic pages', () => {
+ /** @type {import('../../../astro/test/test-utils').Fixture} */
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: new URL('./fixtures/dynamic-route/', import.meta.url).toString(),
+ experimental: {
+ ssr: true,
+ },
+ adapter: netlifyAdapter({
+ dist: new URL('./fixtures/dynamic-route/dist/', import.meta.url)
+ }),
+ site: `http://example.com`,
+ vite: {
+ resolve: {
+ alias: {
+ '@astrojs/netlify/netlify-functions.js': fileURLToPath(new URL('../dist/netlify-functions.js', import.meta.url))
+ }
+ }
+ }
+ });
+ await fixture.build();
+ });
+
+ it('Dynamic pages are included in the redirects file', async () => {
+ const redir = await fixture.readFile('/_redirects');
+ expect(redir).to.match(/\/products\/\*/);
+ });
+});
diff --git a/packages/integrations/netlify/test/fixtures/.gitignore b/packages/integrations/netlify/test/fixtures/.gitignore
new file mode 100644
index 000000000..916f60644
--- /dev/null
+++ b/packages/integrations/netlify/test/fixtures/.gitignore
@@ -0,0 +1 @@
+**/netlify
diff --git a/packages/integrations/netlify/test/fixtures/dynamic-route/src/pages/products/[id].astro b/packages/integrations/netlify/test/fixtures/dynamic-route/src/pages/products/[id].astro
new file mode 100644
index 000000000..5ed06d251
--- /dev/null
+++ b/packages/integrations/netlify/test/fixtures/dynamic-route/src/pages/products/[id].astro
@@ -0,0 +1,11 @@
+---
+
+---
+<html>
+<head>
+ <title>Testing</title>
+</head>
+<body>
+ <h1>Testing</h1>
+</body>
+</html>