-
Notifications
You must be signed in to change notification settings - Fork 520
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: experimental
defineRouteMeta
(#2102)
Co-authored-by: Pooya Parsa <pooya@pi0.io> Co-authored-by: Pooya Parsa <pyapar@gmail.com>
- Loading branch information
1 parent
f0997c1
commit da05b8d
Showing
14 changed files
with
227 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import { readFile } from "node:fs/promises"; | ||
import { transform } from "esbuild"; | ||
import type { Plugin } from "rollup"; | ||
import type { Literal, Expression } from "estree"; | ||
import { extname } from "pathe"; | ||
import { Nitro, NitroEventHandler } from "../../types"; | ||
|
||
const virtualPrefix = "\0nitro-handler-meta:"; | ||
|
||
// From esbuild.ts | ||
const esbuildLoaders = { | ||
".ts": "ts", | ||
".js": "js", | ||
".tsx": "tsx", | ||
".jsx": "jsx", | ||
}; | ||
|
||
export function handlersMeta(nitro: Nitro) { | ||
return { | ||
name: "nitro:handlers-meta", | ||
async resolveId(id) { | ||
if (id.startsWith("\0")) { | ||
return; | ||
} | ||
if (id.endsWith(`?meta`)) { | ||
const resolved = await this.resolve(id.replace(`?meta`, ``)); | ||
return virtualPrefix + resolved.id; | ||
} | ||
}, | ||
load(id) { | ||
if (id.startsWith(virtualPrefix)) { | ||
const fullPath = id.slice(virtualPrefix.length); | ||
return readFile(fullPath, { encoding: "utf8" }); | ||
} | ||
}, | ||
async transform(code, id) { | ||
if (!id.startsWith(virtualPrefix)) { | ||
return; | ||
} | ||
|
||
let meta: NitroEventHandler["meta"] | null = null; | ||
|
||
try { | ||
const ext = extname(id); | ||
const jsCode = await transform(code, { | ||
loader: esbuildLoaders[ext], | ||
}).then((r) => r.code); | ||
const ast = this.parse(jsCode); | ||
for (const node of ast.body) { | ||
if ( | ||
node.type === "ExpressionStatement" && | ||
node.expression.type === "CallExpression" && | ||
node.expression.callee.type === "Identifier" && | ||
node.expression.callee.name === "defineRouteMeta" && | ||
node.expression.arguments.length === 1 | ||
) { | ||
meta = astToObject(node.expression.arguments[0] as any); | ||
break; | ||
} | ||
} | ||
} catch (err) { | ||
console.warn( | ||
`[nitro] [handlers-meta] Cannot extra route meta for: ${id}: ${err}` | ||
); | ||
} | ||
|
||
return { | ||
code: `export default ${JSON.stringify(meta)};`, | ||
map: null, | ||
}; | ||
}, | ||
} satisfies Plugin; | ||
} | ||
|
||
function astToObject(node: Expression | Literal) { | ||
switch (node.type) { | ||
case "ObjectExpression": { | ||
const obj: Record<string, any> = {}; | ||
for (const prop of node.properties) { | ||
if (prop.type === "Property") { | ||
const key = (prop.key as any).name; | ||
obj[key] = astToObject(prop.value as any); | ||
} | ||
} | ||
return obj; | ||
} | ||
case "ArrayExpression": { | ||
return node.elements.map((el) => astToObject(el as any)).filter(Boolean); | ||
} | ||
case "Literal": { | ||
return node.value; | ||
} | ||
// No default | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import type { NitroRouteMeta } from "nitropack"; | ||
|
||
export function defineRouteMeta(meta: NitroRouteMeta) { | ||
return meta; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import type { OperationObject } from "openapi-typescript"; | ||
import { NitroRouteMeta } from "../../types"; | ||
|
||
export const handlersMeta: { | ||
route?: string; | ||
method?: string; | ||
meta?: NitroRouteMeta; | ||
}[]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
defineRouteMeta({ | ||
openAPI: { | ||
tags: ["test"], | ||
description: "Test route description", | ||
parameters: [{ in: "query", name: "test", required: true }], | ||
}, | ||
}); | ||
|
||
export default defineEventHandler(() => "OK"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters