Conform to API route signature (#3272)
* Conform to API route signature * Rename to API route * Update ssr test * Update packages/astro/test/fixtures/ssr-dynamic/src/pages/api/products/[id].js Co-authored-by: Ben Holmes <hey@bholmes.dev> * Adds a changeset * Make PR review changes Co-authored-by: Ben Holmes <hey@bholmes.dev>
This commit is contained in:
parent
d825d376f8
commit
6643a3931d
9 changed files with 179 additions and 3 deletions
5
.changeset/fast-dolls-eat.md
Normal file
5
.changeset/fast-dolls-eat.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Implements the Dynamic Route API RFC
|
|
@ -856,12 +856,27 @@ export interface AstroAdapter {
|
|||
args?: any;
|
||||
}
|
||||
|
||||
export interface APIContext {
|
||||
params: Params;
|
||||
request: Request;
|
||||
}
|
||||
|
||||
export interface EndpointOutput<Output extends Body = Body> {
|
||||
body: Output;
|
||||
}
|
||||
|
||||
interface APIRoute {
|
||||
(context: APIContext): EndpointOutput | Response;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Use { context: APIRouteContext } object instead.
|
||||
*/
|
||||
(params: Params, request: Request): EndpointOutput | Response;
|
||||
}
|
||||
|
||||
export interface EndpointHandler {
|
||||
[method: string]: (params: any, request: Request) => EndpointOutput | Response;
|
||||
[method: string]: APIRoute;
|
||||
}
|
||||
|
||||
export interface AstroRenderer {
|
||||
|
|
|
@ -52,6 +52,7 @@ export async function callGetStaticPaths({
|
|||
|
||||
const keyedStaticPaths = staticPaths as GetStaticPathsResultKeyed;
|
||||
keyedStaticPaths.keyed = new Map<string, GetStaticPathsItem>();
|
||||
|
||||
for (const sp of keyedStaticPaths) {
|
||||
const paramsKey = stringifyParams(sp.params);
|
||||
keyedStaticPaths.keyed.set(paramsKey, sp);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import type {
|
||||
APIContext,
|
||||
AstroComponentMetadata,
|
||||
AstroGlobalPartial,
|
||||
EndpointHandler,
|
||||
|
@ -468,7 +469,46 @@ export async function renderEndpoint(mod: EndpointHandler, request: Request, par
|
|||
`Endpoint handler not found! Expected an exported function for "${chosenMethod}"`
|
||||
);
|
||||
}
|
||||
return await handler.call(mod, params, request);
|
||||
|
||||
if(handler.length > 1) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(`
|
||||
API routes with 2 arguments have been deprecated. Instead they take a single argument in the form of:
|
||||
|
||||
export function get({ params, request }) {
|
||||
//...
|
||||
}
|
||||
|
||||
Update your code to remove this warning.`)
|
||||
}
|
||||
|
||||
const context = {
|
||||
request,
|
||||
params
|
||||
};
|
||||
|
||||
const proxy = new Proxy(context, {
|
||||
get(target, prop) {
|
||||
if(prop in target) {
|
||||
return Reflect.get(target, prop);
|
||||
} else if(prop in params) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(`
|
||||
API routes no longer pass params as the first argument. Instead an object containing a params property is provided in the form of:
|
||||
|
||||
export function get({ params }) {
|
||||
// ...
|
||||
}
|
||||
|
||||
Update your code to remove this warning.`);
|
||||
return Reflect.get(params, prop);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}) as APIContext & Params;
|
||||
|
||||
return await handler.call(mod, proxy, request);
|
||||
}
|
||||
|
||||
async function replaceHeadInjection(result: SSRResult, html: string): Promise<string> {
|
||||
|
|
44
packages/astro/test/api-routes.test.js
Normal file
44
packages/astro/test/api-routes.test.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
import { expect } from 'chai';
|
||||
import * as cheerio from 'cheerio';
|
||||
import { loadFixture } from './test-utils.js';
|
||||
|
||||
describe('API routes', () => {
|
||||
let fixture;
|
||||
|
||||
before(async () => {
|
||||
fixture = await loadFixture({ root: './fixtures/api-routes/' });
|
||||
await fixture.build();
|
||||
});
|
||||
|
||||
describe('Deprecated API', () => {
|
||||
it('two argument supported', async () => {
|
||||
const one = JSON.parse(await fixture.readFile('/old-api/twoarg/one.json'));
|
||||
expect(one).to.deep.equal({
|
||||
param: 'one',
|
||||
pathname: '/old-api/twoarg/one.json'
|
||||
});
|
||||
const two = JSON.parse(await fixture.readFile('/old-api/twoarg/two.json'));
|
||||
expect(two).to.deep.equal({
|
||||
param: 'two',
|
||||
pathname: '/old-api/twoarg/two.json'
|
||||
});
|
||||
});
|
||||
|
||||
it('param first argument is supported', async () => {
|
||||
const one = JSON.parse(await fixture.readFile('/old-api/onearg/one.json'));
|
||||
expect(one).to.deep.equal({
|
||||
param: 'one'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('1.0 API', () => {
|
||||
it('Receives a context argument', async () => {
|
||||
const one = JSON.parse(await fixture.readFile('/context/data/one.json'));
|
||||
expect(one).to.deep.equal({
|
||||
param: 'one',
|
||||
pathname: '/context/data/one.json'
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
24
packages/astro/test/fixtures/api-routes/src/pages/context/data/[param].json.js
vendored
Normal file
24
packages/astro/test/fixtures/api-routes/src/pages/context/data/[param].json.js
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
export function getStaticPaths() {
|
||||
return [
|
||||
{
|
||||
params: {
|
||||
param: 'one'
|
||||
}
|
||||
},
|
||||
{
|
||||
params: {
|
||||
param: 'two'
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
export function get({ params, request }) {
|
||||
return {
|
||||
body: JSON.stringify({
|
||||
param: params.param,
|
||||
pathname: new URL(request.url).pathname
|
||||
})
|
||||
};
|
||||
}
|
23
packages/astro/test/fixtures/api-routes/src/pages/old-api/onearg/[param].json.js
vendored
Normal file
23
packages/astro/test/fixtures/api-routes/src/pages/old-api/onearg/[param].json.js
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
|
||||
export function getStaticPaths() {
|
||||
return [
|
||||
{
|
||||
params: {
|
||||
param: 'one'
|
||||
}
|
||||
},
|
||||
{
|
||||
params: {
|
||||
param: 'two'
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
export function get(params) {
|
||||
return {
|
||||
body: JSON.stringify({
|
||||
param: params.param
|
||||
})
|
||||
};
|
||||
}
|
24
packages/astro/test/fixtures/api-routes/src/pages/old-api/twoarg/[param].json.js
vendored
Normal file
24
packages/astro/test/fixtures/api-routes/src/pages/old-api/twoarg/[param].json.js
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
export function getStaticPaths() {
|
||||
return [
|
||||
{
|
||||
params: {
|
||||
param: 'one'
|
||||
}
|
||||
},
|
||||
{
|
||||
params: {
|
||||
param: 'two'
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
export function get(params, request) {
|
||||
return {
|
||||
body: JSON.stringify({
|
||||
param: params.param,
|
||||
pathname: new URL(request.url).pathname
|
||||
})
|
||||
};
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
export function get(params) {
|
||||
export function get({ params }) {
|
||||
return {
|
||||
body: JSON.stringify(params)
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue