diff options
author | 2022-05-04 14:55:37 -0400 | |
---|---|---|
committer | 2022-05-04 14:55:37 -0400 | |
commit | 6643a3931d45e63363599bb0cf7b2b2951266cfb (patch) | |
tree | ed58c3531fb0da64ac6f94ab3dac2fb6117dda7a | |
parent | d825d376f8a2548a25accee0dfe71e03ecd83d7e (diff) | |
download | astro-6643a3931d45e63363599bb0cf7b2b2951266cfb.tar.gz astro-6643a3931d45e63363599bb0cf7b2b2951266cfb.tar.zst astro-6643a3931d45e63363599bb0cf7b2b2951266cfb.zip |
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>
9 files changed, 179 insertions, 3 deletions
diff --git a/.changeset/fast-dolls-eat.md b/.changeset/fast-dolls-eat.md new file mode 100644 index 000000000..3eda1c985 --- /dev/null +++ b/.changeset/fast-dolls-eat.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Implements the Dynamic Route API RFC diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 2848760d2..805eeb407 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -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 { diff --git a/packages/astro/src/core/render/route-cache.ts b/packages/astro/src/core/render/route-cache.ts index b564a6ca6..762128555 100644 --- a/packages/astro/src/core/render/route-cache.ts +++ b/packages/astro/src/core/render/route-cache.ts @@ -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); diff --git a/packages/astro/src/runtime/server/index.ts b/packages/astro/src/runtime/server/index.ts index c9df2e62b..dd278ae5a 100644 --- a/packages/astro/src/runtime/server/index.ts +++ b/packages/astro/src/runtime/server/index.ts @@ -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> { diff --git a/packages/astro/test/api-routes.test.js b/packages/astro/test/api-routes.test.js new file mode 100644 index 000000000..d7d0c3d29 --- /dev/null +++ b/packages/astro/test/api-routes.test.js @@ -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' + }); + }); + }); +}); diff --git a/packages/astro/test/fixtures/api-routes/src/pages/context/data/[param].json.js b/packages/astro/test/fixtures/api-routes/src/pages/context/data/[param].json.js new file mode 100644 index 000000000..2ed42a5ec --- /dev/null +++ b/packages/astro/test/fixtures/api-routes/src/pages/context/data/[param].json.js @@ -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 + }) + }; +} diff --git a/packages/astro/test/fixtures/api-routes/src/pages/old-api/onearg/[param].json.js b/packages/astro/test/fixtures/api-routes/src/pages/old-api/onearg/[param].json.js new file mode 100644 index 000000000..63771f8e0 --- /dev/null +++ b/packages/astro/test/fixtures/api-routes/src/pages/old-api/onearg/[param].json.js @@ -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 + }) + }; +} diff --git a/packages/astro/test/fixtures/api-routes/src/pages/old-api/twoarg/[param].json.js b/packages/astro/test/fixtures/api-routes/src/pages/old-api/twoarg/[param].json.js new file mode 100644 index 000000000..ab71d6896 --- /dev/null +++ b/packages/astro/test/fixtures/api-routes/src/pages/old-api/twoarg/[param].json.js @@ -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 + }) + }; +} diff --git a/packages/astro/test/fixtures/ssr-dynamic/src/pages/api/products/[id].js b/packages/astro/test/fixtures/ssr-dynamic/src/pages/api/products/[id].js index 2d619ee74..4d96b62a5 100644 --- a/packages/astro/test/fixtures/ssr-dynamic/src/pages/api/products/[id].js +++ b/packages/astro/test/fixtures/ssr-dynamic/src/pages/api/products/[id].js @@ -1,5 +1,5 @@ -export function get(params) { +export function get({ params }) { return { body: JSON.stringify(params) }; |