UNPKG

@sapphire/plugin-api

Version:

Plugin for @sapphire/framework to expose a REST API

1 lines 5.63 kB
{"version":3,"sources":["../../../../src/lib/structures/Route.ts"],"names":[],"mappings":";;;;;AA4CO,IAAe,MAAA,GAAf,MAAe,MAAA,SAA6D,KAAyB,CAAA;AAAA,EAgBpG,WAAY,CAAA,OAAA,EAA8B,OAAmB,GAAA,EAAe,EAAA;AAClF,IAAA,KAAA,CAAM,SAAS,OAAO,CAAA;AAbvB;AAAA;AAAA;AAAA,IAAgB,aAAA,CAAA,IAAA,EAAA,mBAAA,CAAA;AAKhB;AAAA;AAAA;AAAA,IAAgB,aAAA,CAAA,IAAA,EAAA,MAAA,CAAA;AAKhB;AAAA;AAAA;AAAA,IAAgB,aAAA,CAAA,IAAA,EAAA,SAAA,CAAA;AAKf,IAAM,MAAA,GAAA,GAAM,IAAK,CAAA,SAAA,CAAU,MAAO,CAAA,OAAA;AAElC,IAAA,MAAM,IAAO,GAAA,UAAA,CAAW,SAAU,CAAA,GAAA,CAAI,MAAM,CAAA;AAC5C,IAAA,MAAM,OAAU,GAAA,IAAI,GAAI,CAAA,OAAA,CAAQ,OAAO,CAAA;AACvC,IAAA,IAAI,QAAQ,KAAO,EAAA;AAElB,MAAA,IAAA,CAAK,KAAK,GAAG,UAAA,CAAW,SAAU,CAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,KAC1C,MAAA;AAGN,MAAA,IAAI,WAAW,OAAQ,CAAA,IAAA;AACvB,MAAM,MAAA,OAAA,GAAU,UAAW,CAAA,aAAA,CAAc,QAAQ,CAAA;AACjD,MAAI,IAAA,CAAC,SAAU,CAAA,OAAO,CAAG,EAAA;AACxB,QAAA,QAAA,GAAW,SAAS,KAAM,CAAA,CAAA,EAAG,SAAS,MAAS,GAAA,OAAA,CAAQ,SAAS,CAAC,CAAA;AACjE,QAAA,OAAA,CAAQ,IAAI,OAAO,CAAA;AAAA;AAGpB,MAAK,IAAA,CAAA,IAAA,CAAK,GAAG,UAAA,CAAW,SAAU,CAAA,UAAA,CAAW,qBAAsB,CAAA,IAAA,CAAK,QAAS,CAAA,WAAA,EAAa,QAAQ,CAAC,CAAC,CAAA;AAAA;AAGzG,IAAA,IAAA,CAAK,IAAO,GAAA,IAAA;AACZ,IAAA,IAAA,CAAK,OAAU,GAAA,OAAA;AACf,IAAA,IAAA,CAAK,oBAAoB,OAAQ,CAAA,iBAAA,IAAqB,GAAI,CAAA,iBAAA,IAAqB,OAAO,IAAO,GAAA,EAAA;AAAA;AAI/F,CAAA;AA7C4G,MAAA,CAAA,MAAA,EAAA,OAAA,CAAA;AAArG,IAAe,KAAf,GAAA","file":"Route.mjs","sourcesContent":["import { Piece } from '@sapphire/pieces';\nimport { isNullish, type Awaitable } from '@sapphire/utilities';\nimport type { ApiRequest } from './api/ApiRequest';\nimport type { ApiResponse } from './api/ApiResponse';\nimport type { MethodName } from './http/HttpMethods';\nimport { RouterRoot } from './router/RouterRoot';\n\n/**\n * @since 1.0.0\n *\n * @example A simple GET route that returns a JSON response:\n * ```typescript\n * // hello.get.ts\n * import { Route } from '@sapphire/plugin-api';\n *\n * export class MyRoute extends Route {\n * public run(request: Route.Request, response: Route.Response) {\n * return response.json({ message: 'Hello, World!' });\n * }\n * }\n * ```\n *\n * ```bash\n * $ curl http://localhost:4000/hello\n * {\"message\":\"Hello, World!\"}\n * ```\n *\n * @example A simple POST route that reads the body and returns it:\n * ```typescript\n * // echo.post.ts\n * import { Route } from '@sapphire/plugin-api';\n *\n * export class MyRoute extends Route {\n * public run(request: Route.Request, response: Route.Response) {\n * return response.json(request.params);\n * }\n * }\n * ```\n *\n * ```bash\n * $ curl -X POST -H \"Content-Type: application/json\" -d '{\"hello\":\"world\"}' http://localhost:4000/echo\n * {\"hello\":\"world\"}\n * ```\n */\nexport abstract class Route<Options extends Route.Options = Route.Options> extends Piece<Options, 'routes'> {\n\t/**\n\t * (RFC 7230 3.3.2) The maximum decimal number of octets.\n\t */\n\tpublic readonly maximumBodyLength: number;\n\n\t/**\n\t * The path this route represents.\n\t */\n\tpublic readonly path: readonly string[];\n\n\t/**\n\t * The methods this route accepts.\n\t */\n\tpublic readonly methods: ReadonlySet<MethodName>;\n\n\tpublic constructor(context: Route.LoaderContext, options: Options = {} as Options) {\n\t\tsuper(context, options);\n\n\t\tconst api = this.container.server.options;\n\n\t\tconst path = RouterRoot.normalize(api.prefix);\n\t\tconst methods = new Set(options.methods);\n\t\tif (options.route) {\n\t\t\t// If a route is specified, no extra processing is made:\n\t\t\tpath.push(...RouterRoot.normalize(options.route));\n\t\t} else {\n\t\t\t// If a route is not specified, extra processing is made to calculate\n\t\t\t// one from the file system if it's possible:\n\t\t\tlet lastPart = context.name;\n\t\t\tconst implied = RouterRoot.extractMethod(lastPart);\n\t\t\tif (!isNullish(implied)) {\n\t\t\t\tlastPart = lastPart.slice(0, lastPart.length - implied.length - 1);\n\t\t\t\tmethods.add(implied);\n\t\t\t}\n\n\t\t\tpath.push(...RouterRoot.normalize(RouterRoot.makeRoutePathForPiece(this.location.directories, lastPart)));\n\t\t}\n\n\t\tthis.path = path;\n\t\tthis.methods = methods;\n\t\tthis.maximumBodyLength = options.maximumBodyLength ?? api.maximumBodyLength ?? 1024 * 1024 * 50;\n\t}\n\n\tpublic abstract run(request: Route.Request, response: Route.Response): Awaitable<unknown>;\n}\n\nexport interface RouteOptions extends Piece.Options {\n\t/**\n\t * The route the piece should represent.\n\t * @since 1.0.0\n\t *\n\t * @defaultValue The filesystem-based path, or the name if the location is virtual.\n\t *\n\t * @example\n\t * ```typescript\n\t * '/users'\n\t * // request.params -> {}\n\t * ```\n\t * @example\n\t * ```typescript\n\t * '/guilds/[guild]/members/[member]'\n\t * // request.params -> { guild: '...', member: '...' }\n\t * ```\n\t */\n\troute?: string;\n\n\t/**\n\t * (RFC 7230 3.3.2) The maximum decimal number of octets.\n\t * @since 1.0.0\n\t *\n\t * @defaultValue this.context.server.options.maximumBodyLength ?? 1024 * 1024 * 50\n\t */\n\tmaximumBodyLength?: number;\n\n\t/**\n\t * The methods this route accepts.\n\t * @since 7.0.0\n\t *\n\t * @defaultValue The method defined in the piece name, or none if not set.\n\t */\n\tmethods?: readonly MethodName[];\n}\n\nexport namespace Route {\n\t/** @deprecated Use {@linkcode LoaderContext} instead. */\n\texport type Context = LoaderContext; // NOSONAR\n\texport type LoaderContext = Piece.LoaderContext<'routes'>;\n\texport type Options = RouteOptions;\n\texport type JSON = Piece.JSON;\n\texport type LocationJSON = Piece.LocationJSON;\n\n\texport type Request = ApiRequest;\n\texport type Response = ApiResponse;\n}\n"]}