@navios/core 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/lib/{index-C0Sg16Eb.d.cts → index-3LcTrbxz.d.mts} +491 -52
  3. package/lib/index-3LcTrbxz.d.mts.map +1 -0
  4. package/lib/{index-DySQ6Dpd.d.mts → index-B14SekVb.d.cts} +491 -52
  5. package/lib/index-B14SekVb.d.cts.map +1 -0
  6. package/lib/index.cjs +18 -3
  7. package/lib/index.d.cts +2 -2
  8. package/lib/index.d.mts +2 -2
  9. package/lib/index.mjs +4 -4
  10. package/lib/legacy-compat/index.cjs +3 -3
  11. package/lib/legacy-compat/index.d.cts +1 -1
  12. package/lib/legacy-compat/index.d.mts +1 -1
  13. package/lib/legacy-compat/index.mjs +2 -2
  14. package/lib/{navios.factory-CO5MB_OK.cjs → navios.factory-CUrO_p6K.cjs} +461 -48
  15. package/lib/navios.factory-CUrO_p6K.cjs.map +1 -0
  16. package/lib/{navios.factory-D6Y94P9B.mjs → navios.factory-DjUOOVVL.mjs} +372 -49
  17. package/lib/navios.factory-DjUOOVVL.mjs.map +1 -0
  18. package/lib/testing/index.cjs +2 -2
  19. package/lib/testing/index.d.cts +1 -1
  20. package/lib/testing/index.d.mts +1 -1
  21. package/lib/testing/index.mjs +2 -2
  22. package/lib/{tokens-CWw9kyeD.cjs → tokens-BEuBMGGX.cjs} +18 -21
  23. package/lib/tokens-BEuBMGGX.cjs.map +1 -0
  24. package/lib/{tokens-4J9sredA.mjs → tokens-COyNGV1I.mjs} +17 -20
  25. package/lib/tokens-COyNGV1I.mjs.map +1 -0
  26. package/lib/{use-guards.decorator-BecoQSmE.mjs → use-guards.decorator-DLmRl2CV.mjs} +14 -17
  27. package/lib/use-guards.decorator-DLmRl2CV.mjs.map +1 -0
  28. package/lib/{use-guards.decorator-C4ml9XaT.cjs → use-guards.decorator-DhumFTk3.cjs} +15 -18
  29. package/lib/use-guards.decorator-DhumFTk3.cjs.map +1 -0
  30. package/package.json +2 -2
  31. package/src/interfaces/index.mts +3 -0
  32. package/src/interfaces/plugin-context.mts +104 -0
  33. package/src/interfaces/plugin-stage.mts +62 -0
  34. package/src/interfaces/plugin.interface.mts +42 -62
  35. package/src/interfaces/staged-plugin.interface.mts +209 -0
  36. package/src/metadata/controller.metadata.mts +29 -22
  37. package/src/metadata/module.metadata.mts +33 -25
  38. package/src/navios.application.mts +247 -53
  39. package/src/services/module-loader.service.mts +11 -8
  40. package/src/utils/define-plugin.mts +251 -0
  41. package/src/utils/index.mts +1 -0
  42. package/lib/index-C0Sg16Eb.d.cts.map +0 -1
  43. package/lib/index-DySQ6Dpd.d.mts.map +0 -1
  44. package/lib/navios.factory-CO5MB_OK.cjs.map +0 -1
  45. package/lib/navios.factory-D6Y94P9B.mjs.map +0 -1
  46. package/lib/tokens-4J9sredA.mjs.map +0 -1
  47. package/lib/tokens-CWw9kyeD.cjs.map +0 -1
  48. package/lib/use-guards.decorator-BecoQSmE.mjs.map +0 -1
  49. package/lib/use-guards.decorator-C4ml9XaT.cjs.map +0 -1
@@ -1,4 +1,4 @@
1
- import { h as getModuleMetadata, n as StreamAdapterToken, o as MultipartAdapterToken, u as EndpointAdapterToken } from "./tokens-4J9sredA.mjs";
1
+ import { h as getModuleMetadata, n as StreamAdapterToken, o as MultipartAdapterToken, u as EndpointAdapterToken } from "./tokens-COyNGV1I.mjs";
2
2
  import { Injectable, InjectableScope, InjectionToken } from "@navios/di";
3
3
 
4
4
  //#region src/metadata/handler.metadata.mts
@@ -44,21 +44,18 @@ function getEndpointMetadata(target, context) {
44
44
  //#region src/metadata/controller.metadata.mts
45
45
  const ControllerMetadataKey = Symbol("ControllerMetadataKey");
46
46
  function getControllerMetadata(target, context) {
47
- if (context.metadata) {
48
- const metadata = context.metadata[ControllerMetadataKey];
49
- if (metadata) return metadata;
50
- else {
51
- const newMetadata = {
52
- endpoints: getAllEndpointMetadata(context),
53
- guards: /* @__PURE__ */ new Set(),
54
- customAttributes: /* @__PURE__ */ new Map()
55
- };
56
- context.metadata[ControllerMetadataKey] = newMetadata;
57
- target[ControllerMetadataKey] = newMetadata;
58
- return newMetadata;
59
- }
60
- }
61
- throw new Error("[Navios] Wrong environment.");
47
+ if (!context.metadata) throw new Error("[Navios] Wrong environment.");
48
+ const existingMetadata = context.metadata[ControllerMetadataKey];
49
+ if (existingMetadata) return existingMetadata;
50
+ const newMetadata = {
51
+ name: target.name,
52
+ endpoints: getAllEndpointMetadata(context),
53
+ guards: /* @__PURE__ */ new Set(),
54
+ customAttributes: /* @__PURE__ */ new Map()
55
+ };
56
+ context.metadata[ControllerMetadataKey] = newMetadata;
57
+ target[ControllerMetadataKey] = newMetadata;
58
+ return newMetadata;
62
59
  }
63
60
  function extractControllerMetadata(target) {
64
61
  const metadata = target[ControllerMetadataKey];
@@ -336,4 +333,4 @@ function Stream(endpoint) {
336
333
 
337
334
  //#endregion
338
335
  export { getAllEndpointMetadata as _, HttpCode as a, Controller as c, hasManagedMetadata as d, ControllerMetadataKey as f, EndpointMetadataKey as g, hasControllerMetadata as h, Module as i, NaviosManagedMetadataKey as l, getControllerMetadata as m, Stream as n, Header as o, extractControllerMetadata as p, Multipart as r, Endpoint as s, UseGuards as t, getManagedMetadata as u, getEndpointMetadata as v };
339
- //# sourceMappingURL=use-guards.decorator-BecoQSmE.mjs.map
336
+ //# sourceMappingURL=use-guards.decorator-DLmRl2CV.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-guards.decorator-DLmRl2CV.mjs","names":["EndpointMetadataKey","Symbol","getAllEndpointMetadata","context","metadata","Set","Error","getEndpointMetadata","target","endpointMetadata","Array","from","find","item","classMethod","name","newMetadata","url","successStatusCode","adapterToken","headers","httpMethod","config","guards","customAttributes","Map","add","getAllEndpointMetadata","ControllerMetadataKey","Symbol","getControllerMetadata","target","context","metadata","Error","existingMetadata","newMetadata","name","endpoints","guards","Set","customAttributes","Map","extractControllerMetadata","hasControllerMetadata","NaviosManagedMetadataKey","Symbol","getManagedMetadata","target","hasManagedMetadata","Injectable","InjectionToken","getControllerMetadata","Controller","guards","registry","priority","scope","target","context","kind","Error","token","create","metadata","controllerMetadata","guard","Array","from","reverse","add","getEndpointMetadata","EndpointAdapterToken","Endpoint","endpoint","target","context","kind","Error","config","metadata","endpointMetadata","url","method","adapterToken","classMethod","name","httpMethod","getEndpointMetadata","Header","name","value","target","context","kind","Error","metadata","headers","getEndpointMetadata","HttpCode","code","target","context","kind","Error","metadata","successStatusCode","Injectable","InjectableScope","InjectionToken","getModuleMetadata","Module","controllers","imports","guards","overrides","priority","registry","target","context","kind","Error","token","create","moduleMetadata","controller","add","importedModule","guard","Array","from","reverse","override","scope","Singleton","getEndpointMetadata","MultipartAdapterToken","Multipart","endpoint","target","context","kind","Error","config","metadata","endpointMetadata","url","method","adapterToken","classMethod","name","httpMethod","getEndpointMetadata","StreamAdapterToken","Stream","endpoint","target","context","kind","Error","config","metadata","endpointMetadata","url","method","adapterToken","classMethod","name","httpMethod","getControllerMetadata","getEndpointMetadata","UseGuards","guards","target","context","kind","controllerMetadata","guard","reverse","add","endpointMetadata","Error"],"sources":["../src/metadata/handler.metadata.mts","../src/metadata/controller.metadata.mts","../src/metadata/navios-managed.metadata.mts","../src/decorators/controller.decorator.mts","../src/decorators/endpoint.decorator.mts","../src/decorators/header.decorator.mts","../src/decorators/http-code.decorator.mts","../src/decorators/module.decorator.mts","../src/decorators/multipart.decorator.mts","../src/decorators/stream.decorator.mts","../src/decorators/use-guards.decorator.mts"],"sourcesContent":["import type { HttpMethod } from '@navios/builder'\nimport type { ClassTypeWithInstance, InjectionToken } from '@navios/di'\n\nimport type {\n AbstractHttpHandlerAdapterInterface,\n CanActivate,\n HttpHeader,\n} from '../interfaces/index.mjs'\n\nexport const EndpointMetadataKey = Symbol('EndpointMetadataKey')\n\nexport interface HandlerMetadata<Config = null> {\n classMethod: string\n url: string\n successStatusCode: number\n adapterToken:\n | InjectionToken<AbstractHttpHandlerAdapterInterface, undefined>\n | ClassTypeWithInstance<AbstractHttpHandlerAdapterInterface>\n | null\n headers: Partial<Record<HttpHeader, number | string | string[] | undefined>>\n httpMethod: HttpMethod\n config: Config\n guards: Set<\n ClassTypeWithInstance<CanActivate> | InjectionToken<CanActivate, undefined>\n >\n customAttributes: Map<string | symbol, any>\n}\n\nexport function getAllEndpointMetadata(\n context: ClassMethodDecoratorContext | ClassDecoratorContext,\n): Set<HandlerMetadata<any>> {\n if (context.metadata) {\n const metadata = context.metadata[EndpointMetadataKey] as\n | Set<HandlerMetadata>\n | undefined\n if (metadata) {\n return metadata\n } else {\n context.metadata[EndpointMetadataKey] = new Set<HandlerMetadata<any>>()\n return context.metadata[EndpointMetadataKey] as Set<HandlerMetadata<any>>\n }\n }\n throw new Error('[Navios] Wrong environment.')\n}\n\nexport function getEndpointMetadata<Config = any>(\n target: Function,\n context: ClassMethodDecoratorContext,\n): HandlerMetadata<Config> {\n if (context.metadata) {\n const metadata = getAllEndpointMetadata(context)\n if (metadata) {\n const endpointMetadata = Array.from(metadata).find(\n (item) => item.classMethod === target.name,\n )\n if (endpointMetadata) {\n return endpointMetadata\n } else {\n const newMetadata: HandlerMetadata<Config> = {\n classMethod: target.name,\n url: '',\n successStatusCode: 200,\n adapterToken: null,\n headers: {},\n httpMethod: 'GET',\n // @ts-expect-error We are using a generic type here\n config: null,\n guards: new Set<\n | ClassTypeWithInstance<CanActivate>\n | InjectionToken<CanActivate, undefined>\n >(),\n customAttributes: new Map<string | symbol, any>(),\n }\n metadata.add(newMetadata)\n return newMetadata\n }\n }\n }\n throw new Error('[Navios] Wrong environment.')\n}\n","import type {\n ClassType,\n ClassTypeWithInstance,\n InjectionToken,\n} from '@navios/di'\n\nimport type { CanActivate } from '../interfaces/index.mjs'\nimport type { HandlerMetadata } from './handler.metadata.mjs'\n\nimport { getAllEndpointMetadata } from './handler.metadata.mjs'\n\nexport const ControllerMetadataKey = Symbol('ControllerMetadataKey')\n\nexport interface ControllerMetadata {\n /**\n * The name of the controller class.\n */\n name: string\n endpoints: Set<HandlerMetadata>\n guards: Set<\n ClassTypeWithInstance<CanActivate> | InjectionToken<CanActivate, undefined>\n >\n customAttributes: Map<string | symbol, any>\n}\n\nexport function getControllerMetadata(\n target: ClassType,\n context: ClassDecoratorContext,\n): ControllerMetadata {\n if (!context.metadata) {\n throw new Error('[Navios] Wrong environment.')\n }\n\n const existingMetadata = context.metadata[ControllerMetadataKey] as\n | ControllerMetadata\n | undefined\n\n if (existingMetadata) {\n return existingMetadata\n }\n\n const newMetadata: ControllerMetadata = {\n name: target.name,\n endpoints: getAllEndpointMetadata(context),\n guards: new Set<\n ClassTypeWithInstance<CanActivate> | InjectionToken<CanActivate, undefined>\n >(),\n customAttributes: new Map<string | symbol, any>(),\n }\n\n context.metadata[ControllerMetadataKey] = newMetadata\n // @ts-expect-error We add a custom metadata key to the target\n target[ControllerMetadataKey] = newMetadata\n\n return newMetadata\n}\n\nexport function extractControllerMetadata(\n target: ClassType,\n): ControllerMetadata {\n // @ts-expect-error We add a custom metadata key to the target\n const metadata = target[ControllerMetadataKey] as\n | ControllerMetadata\n | undefined\n if (!metadata) {\n throw new Error(\n '[Navios] Controller metadata not found. Make sure to use @Controller decorator.',\n )\n }\n return metadata\n}\n\nexport function hasControllerMetadata(target: ClassType): boolean {\n // @ts-expect-error We add a custom metadata key to the target\n const metadata = target[ControllerMetadataKey] as\n | ControllerMetadata\n | undefined\n return !!metadata\n}\n","import type { ClassType } from '@navios/di'\n\n/**\n * Symbol used to identify Navios-managed classes (Controller, Module, MessageController, etc.).\n * This allows AttributeFactory to work with any Navios-managed class type generically.\n */\nexport const NaviosManagedMetadataKey = Symbol('NaviosManagedMetadataKey')\n\n/**\n * Interface for metadata that has custom attributes.\n * Used by Navios-managed classes (Controller, Module, MessageController, etc.).\n */\nexport interface ManagedMetadata {\n customAttributes: Map<string | symbol, any>\n}\n\n/**\n * Gets managed metadata from a class if it exists.\n * This is a generic function that works with any Navios-managed class type.\n *\n * @param target - The class to check\n * @returns The metadata with customAttributes, or null if not managed\n */\nexport function getManagedMetadata(target: ClassType): ManagedMetadata | null {\n // @ts-expect-error - Checking for managed metadata key\n if (target[NaviosManagedMetadataKey]) {\n // @ts-expect-error - Accessing managed metadata\n return target[NaviosManagedMetadataKey] as ManagedMetadata\n }\n return null\n}\n\n/**\n * Checks if a class is Navios-managed (has managed metadata).\n *\n * @param target - The class to check\n * @returns true if the class is Navios-managed\n */\nexport function hasManagedMetadata(target: ClassType): boolean {\n return getManagedMetadata(target) !== null\n}\n\n","import type { ClassType, InjectableScope } from '@navios/di'\n\nimport { Injectable, InjectionToken, Registry } from '@navios/di'\n\nimport { getControllerMetadata } from '../metadata/index.mjs'\n\n/**\n * Options for configuring a Navios controller.\n */\nexport interface ControllerOptions {\n /**\n * Guards to apply to all endpoints in this controller.\n * Guards are executed in reverse order (last guard first).\n */\n guards?: ClassType[] | Set<ClassType>\n /**\n * Registry to use for the controller.\n * Registry is used to store the controller and its endpoints.\n */\n registry?: Registry\n /**\n * Priority to use for the controller.\n * Priority is used to sort the controller in the registry.\n */\n priority?: number\n /**\n * Scope to use for the controller.\n * Scope is used to determine the scope of the controller.\n */\n scope?: InjectableScope\n}\n\n/**\n * Decorator that marks a class as a Navios controller.\n *\n * Controllers handle HTTP requests and define endpoints.\n * They are request-scoped by default, meaning a new instance is created for each request.\n *\n * @param options - Controller configuration options\n * @returns A class decorator\n *\n * @example\n * ```typescript\n * @Controller({ guards: [AuthGuard] })\n * export class UserController {\n * @Endpoint(getUserEndpoint)\n * async getUser(request: EndpointParams<typeof getUserEndpoint>) {\n * // Handle request\n * }\n * }\n * ```\n */\nexport function Controller({\n guards,\n registry,\n priority,\n scope,\n}: ControllerOptions = {}) {\n return function (target: ClassType, context: ClassDecoratorContext) {\n if (context.kind !== 'class') {\n throw new Error(\n '[Navios] @Controller decorator can only be used on classes.',\n )\n }\n const token = InjectionToken.create(target)\n if (context.metadata) {\n const controllerMetadata = getControllerMetadata(target, context)\n if (guards) {\n for (const guard of Array.from(guards).reverse()) {\n controllerMetadata.guards.add(guard)\n }\n }\n }\n return Injectable({\n token,\n registry,\n priority,\n scope,\n })(target, context)\n }\n}\n","import type {\n EndpointHandler,\n EndpointOptions,\n RequestArgs,\n} from '@navios/builder'\nimport type { z } from 'zod/v4'\n\nimport { ZodDiscriminatedUnion } from 'zod/v4'\n\nimport { getEndpointMetadata } from '../metadata/index.mjs'\nimport { EndpointAdapterToken } from '../tokens/index.mjs'\n\n/**\n * Extracts the typed parameters for an endpoint handler function.\n *\n * This utility type extracts URL parameters, query parameters, and request body\n * from an endpoint declaration and flattens them into a single object.\n *\n * @typeParam EndpointDeclaration - The endpoint declaration from @navios/builder\n *\n * @example\n * ```typescript\n * const getUserEndpoint = api.declareEndpoint({\n * method: 'get',\n * url: '/users/$userId',\n * querySchema: z.object({ include: z.string().optional() }),\n * responseSchema: z.object({ id: z.string(), name: z.string() }),\n * })\n *\n * @Endpoint(getUserEndpoint)\n * async getUser(request: EndpointParams<typeof getUserEndpoint>) {\n * // request.urlParams.userId is typed as string\n * // request.query.include is typed as string | undefined\n * }\n * ```\n */\nexport type EndpointParams<\n EndpointDeclaration extends EndpointHandler<Config, false>,\n Config extends EndpointOptions = EndpointDeclaration['config'],\n> = RequestArgs<\n Config['url'],\n Config['querySchema'],\n Config['requestSchema'],\n Config['urlParamsSchema'],\n true\n>\n\n/**\n * Extracts the typed return value for an endpoint handler function.\n *\n * This utility type extracts the response schema from an endpoint declaration\n * and returns the appropriate Promise type.\n *\n * @typeParam EndpointDeclaration - The endpoint declaration from @navios/builder\n *\n * @example\n * ```typescript\n * const getUserEndpoint = api.declareEndpoint({\n * method: 'get',\n * url: '/users/$userId',\n * responseSchema: z.object({ id: z.string(), name: z.string() }),\n * })\n *\n * @Endpoint(getUserEndpoint)\n * async getUser(request: EndpointParams<typeof getUserEndpoint>): EndpointResult<typeof getUserEndpoint> {\n * return { id: '1', name: 'John' } // Type-checked against responseSchema\n * }\n * ```\n */\nexport type EndpointResult<\n EndpointDeclaration extends {\n config: EndpointOptions\n },\n> =\n EndpointDeclaration['config']['responseSchema'] extends ZodDiscriminatedUnion<\n infer Options\n >\n ? Promise<z.input<Options[number]>>\n : Promise<z.input<EndpointDeclaration['config']['responseSchema']>>\n\n/**\n * Decorator that marks a method as an HTTP endpoint.\n *\n * The endpoint must be defined using @navios/builder's `declareEndpoint` method.\n * This ensures type safety and consistency between client and server.\n *\n * @param endpoint - The endpoint declaration from @navios/builder\n * @returns A method decorator\n *\n * @example\n * ```typescript\n * import { builder } from '@navios/builder'\n *\n * const api = builder()\n * const getUserEndpoint = api.declareEndpoint({\n * method: 'get',\n * url: '/users/$userId',\n * responseSchema: z.object({ id: z.string(), name: z.string() }),\n * })\n *\n * @Controller()\n * export class UserController {\n * @Endpoint(getUserEndpoint)\n * async getUser(request: EndpointParams<typeof getUserEndpoint>) {\n * const { userId } = request.urlParams\n * return { id: userId, name: 'John' }\n * }\n * }\n * ```\n */\nexport function Endpoint<const Config extends EndpointOptions>(\n endpoint: EndpointHandler<Config, false>,\n): (\n target: (\n params: RequestArgs<\n Config['url'],\n Config['querySchema'],\n Config['requestSchema'],\n Config['urlParamsSchema'],\n true\n >,\n ) =>\n | Promise<z.input<Config['responseSchema']>>\n | z.input<Config['responseSchema']>,\n context: ClassMethodDecoratorContext,\n) => void\nexport function Endpoint<const Config extends EndpointOptions>(\n endpoint: EndpointHandler<Config, false>,\n): (\n target: () =>\n | Promise<z.input<Config['responseSchema']>>\n | z.input<Config['responseSchema']>,\n context: ClassMethodDecoratorContext,\n) => void\nexport function Endpoint<const Config extends EndpointOptions>(\n endpoint: EndpointHandler<Config, false>,\n) {\n type Params = RequestArgs<\n Config['url'],\n Config['querySchema'],\n Config['requestSchema'],\n Config['urlParamsSchema'],\n true\n >\n\n type Handler =\n | ((\n params: Params,\n ) =>\n | Promise<z.input<Config['responseSchema']>>\n | z.input<Config['responseSchema']>)\n | (() =>\n | Promise<z.input<Config['responseSchema']>>\n | z.input<Config['responseSchema']>)\n\n return (target: Handler, context: ClassMethodDecoratorContext) => {\n if (context.kind !== 'method') {\n throw new Error(\n '[Navios] Endpoint decorator can only be used on methods.',\n )\n }\n const config = endpoint.config\n if (context.metadata) {\n let endpointMetadata = getEndpointMetadata<EndpointOptions>(\n target,\n context,\n )\n if (endpointMetadata.config && endpointMetadata.config.url) {\n throw new Error(\n `[Navios] Endpoint ${config.method} ${config.url} already exists. Please use a different method or url.`,\n )\n }\n endpointMetadata.config = config\n endpointMetadata.adapterToken = EndpointAdapterToken\n endpointMetadata.classMethod = target.name\n endpointMetadata.httpMethod = config.method\n endpointMetadata.url = config.url\n }\n return target\n }\n}\n","import type { HttpHeader } from '../interfaces/index.mjs'\n\nimport { getEndpointMetadata } from '../metadata/index.mjs'\n\n/**\n * Decorator that sets a custom HTTP response header for an endpoint.\n * \n * @param name - The header name (e.g., 'Content-Type', 'Cache-Control')\n * @param value - The header value (string, number, or array of strings)\n * @returns A method decorator\n * \n * @example\n * ```typescript\n * @Controller()\n * export class UserController {\n * @Endpoint(getUserEndpoint)\n * @Header('Cache-Control', 'max-age=3600')\n * async getUser() {\n * return { id: '1', name: 'John' }\n * }\n * }\n * ```\n */\nexport function Header(name: HttpHeader, value: string | number | string[]) {\n return <T extends Function>(\n target: T,\n context: ClassMethodDecoratorContext,\n ) => {\n if (context.kind !== 'method') {\n throw new Error('[Navios] Header decorator can only be used on methods.')\n }\n const metadata = getEndpointMetadata(target, context)\n\n metadata.headers[name] = value\n\n return target\n }\n}\n","import { getEndpointMetadata } from '../metadata/index.mjs'\n\n/**\n * Decorator that sets a custom HTTP status code for successful responses.\n * \n * By default, endpoints return 200 OK. Use this decorator to return a different status code.\n * \n * @param code - The HTTP status code to return (e.g., 201, 204, 202)\n * @returns A method decorator\n * \n * @example\n * ```typescript\n * @Controller()\n * export class UserController {\n * @Endpoint(createUserEndpoint)\n * @HttpCode(201)\n * async createUser() {\n * return { id: '1', name: 'John' }\n * }\n * }\n * ```\n */\nexport function HttpCode(code: number) {\n return <T extends Function>(\n target: T,\n context: ClassMethodDecoratorContext,\n ) => {\n if (context.kind !== 'method') {\n throw new Error(\n '[Navios] HttpCode decorator can only be used on methods.',\n )\n }\n const metadata = getEndpointMetadata(target, context)\n metadata.successStatusCode = code\n\n return target\n }\n}\n","import type { ClassType, Registry } from '@navios/di'\n\nimport { Injectable, InjectableScope, InjectionToken } from '@navios/di'\n\nimport { getModuleMetadata } from '../metadata/index.mjs'\n\n/**\n * Options for configuring a Navios module.\n */\nexport interface ModuleOptions {\n /**\n * Controllers to register in this module.\n * Controllers handle HTTP requests and define endpoints.\n */\n controllers?: ClassType[] | Set<ClassType>\n /**\n * Other modules to import into this module.\n * Imported modules' controllers and services become available.\n */\n imports?: ClassType[] | Set<ClassType>\n /**\n * Guards to apply to all controllers in this module.\n * Guards are executed in reverse order (last guard first).\n */\n guards?: ClassType[] | Set<ClassType>\n /**\n * Service override classes to import for side effects.\n * These classes are imported to ensure their @Injectable decorators execute,\n * allowing them to register with the DI system. Overrides should use the same\n * InjectionToken as the original service with a higher priority.\n */\n overrides?: ClassType[] | Set<ClassType>\n /**\n * Priority to use for the module.\n * Priority is used to sort the module in the registry.\n */\n priority?: number\n /**\n * Registry to use for the module.\n * Registry is used to store the module and its controllers.\n */\n registry?: Registry\n}\n\n/**\n * Decorator that marks a class as a Navios module.\n *\n * Modules are the basic building blocks of a Navios application.\n * They organize controllers, services, and other modules into logical units.\n *\n * @param options - Module configuration options\n * @returns A class decorator\n *\n * @example\n * ```typescript\n * @Module({\n * controllers: [UserController, AuthController],\n * imports: [DatabaseModule],\n * guards: [AuthGuard],\n * })\n * export class AppModule {}\n * ```\n */\nexport function Module(\n {\n controllers = [],\n imports = [],\n guards = [],\n overrides = [],\n priority,\n registry,\n }: ModuleOptions = {\n controllers: [],\n imports: [],\n guards: [],\n overrides: [],\n },\n) {\n return (target: ClassType, context: ClassDecoratorContext) => {\n if (context.kind !== 'class') {\n throw new Error('[Navios] @Module decorator can only be used on classes.')\n }\n // Register the module in the service locator\n const token = InjectionToken.create(target)\n const moduleMetadata = getModuleMetadata(target, context)\n for (const controller of controllers) {\n moduleMetadata.controllers.add(controller)\n }\n for (const importedModule of imports) {\n moduleMetadata.imports.add(importedModule)\n }\n for (const guard of Array.from(guards).reverse()) {\n moduleMetadata.guards.add(guard)\n }\n for (const override of overrides) {\n moduleMetadata.overrides.add(override)\n }\n\n return Injectable({\n token,\n scope: InjectableScope.Singleton,\n priority,\n registry,\n })(target, context)\n }\n}\n","import type { EndpointOptions, RequestArgs } from '@navios/builder'\nimport type { z, ZodObject, ZodType } from 'zod/v4'\n\nimport { ZodDiscriminatedUnion } from 'zod/v4'\n\nimport { getEndpointMetadata } from '../metadata/index.mjs'\nimport { MultipartAdapterToken } from '../tokens/index.mjs'\n\n/**\n * Extracts the typed parameters for a multipart endpoint handler function.\n *\n * Similar to `EndpointParams`, but specifically for multipart/form-data endpoints.\n *\n * @typeParam EndpointDeclaration - The endpoint declaration from @navios/builder\n */\nexport type MultipartParams<\n EndpointDeclaration extends {\n config: EndpointOptions\n },\n Url extends string = EndpointDeclaration['config']['url'],\n QuerySchema = EndpointDeclaration['config']['querySchema'],\n> = QuerySchema extends ZodObject\n ? EndpointDeclaration['config']['requestSchema'] extends ZodType\n ? RequestArgs<\n Url,\n QuerySchema,\n EndpointDeclaration['config']['requestSchema'],\n EndpointDeclaration['config']['urlParamsSchema'],\n true\n >\n : RequestArgs<\n Url,\n QuerySchema,\n undefined,\n EndpointDeclaration['config']['urlParamsSchema'],\n true\n >\n : EndpointDeclaration['config']['requestSchema'] extends ZodType\n ? RequestArgs<\n Url,\n undefined,\n EndpointDeclaration['config']['requestSchema'],\n EndpointDeclaration['config']['urlParamsSchema'],\n true\n >\n : RequestArgs<\n Url,\n undefined,\n undefined,\n EndpointDeclaration['config']['urlParamsSchema'],\n true\n >\n\n/**\n * Extracts the typed return value for a multipart endpoint handler function.\n *\n * @typeParam EndpointDeclaration - The endpoint declaration from @navios/builder\n */\nexport type MultipartResult<\n EndpointDeclaration extends {\n config: EndpointOptions\n },\n> =\n EndpointDeclaration['config']['responseSchema'] extends ZodDiscriminatedUnion<\n infer Options\n >\n ? Promise<z.input<Options[number]>>\n : Promise<z.input<EndpointDeclaration['config']['responseSchema']>>\n\n/**\n * Decorator that marks a method as a multipart/form-data endpoint.\n *\n * Use this decorator for endpoints that handle file uploads or form data.\n * The endpoint must be defined using @navios/builder's `declareMultipart` method.\n *\n * @param endpoint - The multipart endpoint declaration from @navios/builder\n * @returns A method decorator\n *\n * @example\n * ```typescript\n * const uploadFileEndpoint = api.declareMultipart({\n * method: 'post',\n * url: '/upload',\n * requestSchema: z.object({ file: z.instanceof(File) }),\n * responseSchema: z.object({ url: z.string() }),\n * })\n *\n * @Controller()\n * export class FileController {\n * @Multipart(uploadFileEndpoint)\n * async uploadFile(request: MultipartParams<typeof uploadFileEndpoint>) {\n * const { file } = request.data\n * // Handle file upload\n * return { url: 'https://example.com/file.jpg' }\n * }\n * }\n * ```\n */\nexport function Multipart<Config extends EndpointOptions>(endpoint: {\n config: Config\n}): (\n target: (\n params: RequestArgs<\n Config['url'],\n Config['querySchema'],\n Config['requestSchema'],\n Config['urlParamsSchema'],\n true\n >,\n ) =>\n | Promise<z.input<Config['responseSchema']>>\n | z.input<Config['responseSchema']>,\n context: ClassMethodDecoratorContext,\n) => void\nexport function Multipart<Config extends EndpointOptions>(endpoint: {\n config: Config\n}): (\n target: () =>\n | Promise<z.input<Config['responseSchema']>>\n | z.input<Config['responseSchema']>,\n context: ClassMethodDecoratorContext,\n) => void\nexport function Multipart<Config extends EndpointOptions>(endpoint: {\n config: Config\n}) {\n type Params = RequestArgs<\n Config['url'],\n Config['querySchema'],\n Config['requestSchema'],\n Config['urlParamsSchema'],\n true\n >\n\n type Handler =\n | ((\n params: Params,\n ) =>\n | Promise<z.input<Config['responseSchema']>>\n | z.input<Config['responseSchema']>)\n | (() =>\n | Promise<z.input<Config['responseSchema']>>\n | z.input<Config['responseSchema']>)\n\n return (target: Handler, context: ClassMethodDecoratorContext) => {\n if (context.kind !== 'method') {\n throw new Error(\n '[Navios] Endpoint decorator can only be used on methods.',\n )\n }\n const config = endpoint.config\n if (context.metadata) {\n let endpointMetadata = getEndpointMetadata<EndpointOptions>(\n target,\n context,\n )\n if (endpointMetadata.config && endpointMetadata.config.url) {\n throw new Error(\n `[Navios] Endpoint ${config.method} ${config.url} already exists. Please use a different method or url.`,\n )\n }\n endpointMetadata.config = config\n endpointMetadata.adapterToken = MultipartAdapterToken\n endpointMetadata.classMethod = target.name\n endpointMetadata.httpMethod = config.method\n endpointMetadata.url = config.url\n }\n return target\n }\n}\n","import type {\n BaseEndpointOptions,\n RequestArgs,\n StreamHandler,\n} from '@navios/builder'\nimport type { ZodObject, ZodType } from 'zod/v4'\n\nimport { getEndpointMetadata } from '../metadata/index.mjs'\nimport { StreamAdapterToken } from '../tokens/index.mjs'\n\n/**\n * Extracts the typed parameters for a stream endpoint handler function.\n *\n * Similar to `EndpointParams`, but specifically for streaming endpoints.\n *\n * @typeParam EndpointDeclaration - The stream endpoint declaration from @navios/builder\n */\nexport type StreamParams<\n EndpointDeclaration extends StreamHandler<Config, false>,\n Config extends BaseEndpointOptions = EndpointDeclaration['config'],\n Url extends string = EndpointDeclaration['config']['url'],\n QuerySchema = EndpointDeclaration['config']['querySchema'],\n> = QuerySchema extends ZodObject\n ? EndpointDeclaration['config']['requestSchema'] extends ZodType\n ? RequestArgs<\n Url,\n QuerySchema,\n EndpointDeclaration['config']['requestSchema'],\n EndpointDeclaration['config']['urlParamsSchema'],\n true\n >\n : RequestArgs<\n Url,\n QuerySchema,\n undefined,\n EndpointDeclaration['config']['urlParamsSchema'],\n true\n >\n : EndpointDeclaration['config']['requestSchema'] extends ZodType\n ? RequestArgs<\n Url,\n undefined,\n EndpointDeclaration['config']['requestSchema'],\n EndpointDeclaration['config']['urlParamsSchema'],\n true\n >\n : RequestArgs<\n Url,\n undefined,\n undefined,\n EndpointDeclaration['config']['urlParamsSchema'],\n true\n >\n\n/**\n * Decorator that marks a method as a streaming endpoint.\n *\n * Use this decorator for endpoints that stream data (e.g., file downloads, SSE).\n * The endpoint must be defined using @navios/builder's `declareStream` method.\n *\n * @param endpoint - The stream endpoint declaration from @navios/builder\n * @returns A method decorator\n *\n * @example\n * ```typescript\n * const downloadFileEndpoint = api.declareStream({\n * method: 'get',\n * url: '/files/$fileId',\n * })\n *\n * @Controller()\n * export class FileController {\n * @Stream(downloadFileEndpoint)\n * async downloadFile(request: StreamParams<typeof downloadFileEndpoint>, reply: any) {\n * const { fileId } = request.urlParams\n * // Stream file data to reply\n * }\n * }\n * ```\n */\nexport function Stream<Config extends BaseEndpointOptions>(endpoint: {\n config: Config\n}): (\n target: (\n params: RequestArgs<\n Config['url'],\n Config['querySchema'],\n Config['requestSchema'],\n Config['urlParamsSchema'],\n true\n >,\n reply: any,\n ) => any,\n context: ClassMethodDecoratorContext,\n) => void\n// Bun doesn't support reply parameter\nexport function Stream<Config extends BaseEndpointOptions>(endpoint: {\n config: Config\n}): (\n target: (\n params: RequestArgs<\n Config['url'],\n Config['querySchema'],\n Config['requestSchema'],\n Config['urlParamsSchema'],\n true\n >,\n ) => any,\n context: ClassMethodDecoratorContext,\n) => void\nexport function Stream<Config extends BaseEndpointOptions>(endpoint: {\n config: Config\n}): (target: () => any, context: ClassMethodDecoratorContext) => void\nexport function Stream<Config extends BaseEndpointOptions>(endpoint: {\n config: Config\n}) {\n type Params = RequestArgs<\n Config['url'],\n Config['querySchema'],\n Config['requestSchema'],\n Config['urlParamsSchema'],\n true\n >\n\n type Handler =\n | ((params: Params, reply: any) => any)\n | ((params: Params) => any)\n | (() => any)\n\n return (target: Handler, context: ClassMethodDecoratorContext) => {\n if (context.kind !== 'method') {\n throw new Error(\n '[Navios] Endpoint decorator can only be used on methods.',\n )\n }\n const config = endpoint.config\n if (context.metadata) {\n let endpointMetadata = getEndpointMetadata<BaseEndpointOptions>(\n target,\n context,\n )\n if (endpointMetadata.config && endpointMetadata.config.url) {\n throw new Error(\n `[Navios] Endpoint ${config.method} ${config.url} already exists. Please use a different method or url.`,\n )\n }\n endpointMetadata.config = config\n endpointMetadata.adapterToken = StreamAdapterToken\n endpointMetadata.classMethod = target.name\n endpointMetadata.httpMethod = config.method\n endpointMetadata.url = config.url\n }\n return target\n }\n}\n","import type {\n ClassType,\n ClassTypeWithInstance,\n InjectionToken,\n} from '@navios/di'\n\nimport type { CanActivate } from '../interfaces/index.mjs'\n\nimport {\n getControllerMetadata,\n getEndpointMetadata,\n} from '../metadata/index.mjs'\n\n/**\n * Decorator that applies guards to a controller or endpoint.\n * \n * Guards are used for authentication, authorization, and request validation.\n * They implement the `CanActivate` interface and are executed before the endpoint handler.\n * Guards can be applied at the module, controller, or endpoint level.\n * \n * @param guards - Guard classes or injection tokens to apply\n * @returns A class or method decorator\n * \n * @example\n * ```typescript\n * // Apply to a controller\n * @Controller()\n * @UseGuards(AuthGuard, RoleGuard)\n * export class UserController {\n * @Endpoint(getUserEndpoint)\n * async getUser() { }\n * }\n * \n * // Apply to a specific endpoint\n * @Controller()\n * export class UserController {\n * @Endpoint(getUserEndpoint)\n * @UseGuards(AuthGuard)\n * async getUser() { }\n * }\n * ```\n */\nexport function UseGuards(\n ...guards: (\n | ClassTypeWithInstance<CanActivate>\n | InjectionToken<CanActivate, undefined>\n )[]\n) {\n return function <T extends Function>(\n target: T,\n context: ClassMethodDecoratorContext | ClassDecoratorContext,\n ): T {\n if (context.kind === 'class') {\n const controllerMetadata = getControllerMetadata(\n target as unknown as ClassType,\n context,\n )\n for (const guard of guards.reverse()) {\n controllerMetadata.guards.add(guard)\n }\n } else if (context.kind === 'method') {\n const endpointMetadata = getEndpointMetadata(target, context)\n for (const guard of guards.reverse()) {\n endpointMetadata.guards.add(guard)\n }\n } else {\n throw new Error(\n '[Navios] @UseGuards decorator can only be used on classes or methods.',\n )\n }\n return target\n }\n}\n"],"mappings":";;;;AASA,MAAaA,sBAAsBC,OAAO,sBAAA;AAmB1C,SAAgBC,uBACdC,SAA4D;AAE5D,KAAIA,QAAQC,UAAU;EACpB,MAAMA,WAAWD,QAAQC,SAASJ;AAGlC,MAAII,SACF,QAAOA;OACF;AACLD,WAAQC,SAASJ,uCAAuB,IAAIK,KAAAA;AAC5C,UAAOF,QAAQC,SAASJ;;;AAG5B,OAAM,IAAIM,MAAM,8BAAA;;AAGlB,SAAgBC,oBACdC,QACAL,SAAoC;AAEpC,KAAIA,QAAQC,UAAU;EACpB,MAAMA,WAAWF,uBAAuBC,QAAAA;AACxC,MAAIC,UAAU;GACZ,MAAMK,mBAAmBC,MAAMC,KAAKP,SAAAA,CAAUQ,MAC3CC,SAASA,KAAKC,gBAAgBN,OAAOO,KAAI;AAE5C,OAAIN,iBACF,QAAOA;QACF;IACL,MAAMO,cAAuC;KAC3CF,aAAaN,OAAOO;KACpBE,KAAK;KACLC,mBAAmB;KACnBC,cAAc;KACdC,SAAS,EAAC;KACVC,YAAY;KAEZC,QAAQ;KACRC,wBAAQ,IAAIlB,KAAAA;KAIZmB,kCAAkB,IAAIC,KAAAA;KACxB;AACArB,aAASsB,IAAIV,YAAAA;AACb,WAAOA;;;;AAIb,OAAM,IAAIV,MAAM,8BAAA;;;;;ACnElB,MAAasB,wBAAwBC,OAAO,wBAAA;AAc5C,SAAgBC,sBACdC,QACAC,SAA8B;AAE9B,KAAI,CAACA,QAAQC,SACX,OAAM,IAAIC,MAAM,8BAAA;CAGlB,MAAMC,mBAAmBH,QAAQC,SAASL;AAI1C,KAAIO,iBACF,QAAOA;CAGT,MAAMC,cAAkC;EACtCC,MAAMN,OAAOM;EACbC,WAAWX,uBAAuBK,QAAAA;EAClCO,wBAAQ,IAAIC,KAAAA;EAGZC,kCAAkB,IAAIC,KAAAA;EACxB;AAEAV,SAAQC,SAASL,yBAAyBQ;AAE1CL,QAAOH,yBAAyBQ;AAEhC,QAAOA;;AAGT,SAAgBO,0BACdZ,QAAiB;CAGjB,MAAME,WAAWF,OAAOH;AAGxB,KAAI,CAACK,SACH,OAAM,IAAIC,MACR,kFAAA;AAGJ,QAAOD;;AAGT,SAAgBW,sBAAsBb,QAAiB;AAKrD,QAAO,CAAC,CAHSA,OAAOH;;;;;;;;GCpE1B,MAAaiB,2BAA2BC,OAAO,2BAAA;;;;;;;GAiB/C,SAAgBC,mBAAmBC,QAAiB;AAElD,KAAIA,OAAOH,0BAET,QAAOG,OAAOH;AAEhB,QAAO;;;;;;;GAST,SAAgBI,mBAAmBD,QAAiB;AAClD,QAAOD,mBAAmBC,OAAAA,KAAY;;;;;;;;;;;;;;;;;;;;;;;;GCaxC,SAAgBK,WAAW,EACzBC,QACAC,UACAC,UACAC,UACqB,EAAE,EAAA;AACvB,QAAO,SAAUC,QAAmBC,SAA8B;AAChE,MAAIA,QAAQC,SAAS,QACnB,OAAM,IAAIC,MACR,8DAAA;EAGJ,MAAMC,QAAQX,eAAeY,OAAOL,OAAAA;AACpC,MAAIC,QAAQK,UAAU;GACpB,MAAMC,qBAAqBb,sBAAsBM,QAAQC,QAAAA;AACzD,OAAIL,OACF,MAAK,MAAMY,SAASC,MAAMC,KAAKd,OAAAA,CAAQe,SAAO,CAC5CJ,oBAAmBX,OAAOgB,IAAIJ,MAAAA;;AAIpC,SAAOhB,WAAW;GAChBY;GACAP;GACAC;GACAC;GACF,CAAA,CAAGC,QAAQC,QAAAA;;;;;;ACwDf,SAAgBc,SACdC,UAAwC;AAoBxC,SAAQC,QAAiBC,YAAAA;AACvB,MAAIA,QAAQC,SAAS,SACnB,OAAM,IAAIC,MACR,2DAAA;EAGJ,MAAMC,SAASL,SAASK;AACxB,MAAIH,QAAQI,UAAU;GACpB,IAAIC,mBAAmBV,oBACrBI,QACAC,QAAAA;AAEF,OAAIK,iBAAiBF,UAAUE,iBAAiBF,OAAOG,IACrD,OAAM,IAAIJ,MACR,qBAAqBC,OAAOI,OAAO,GAAGJ,OAAOG,IAAI,wDAAuD;AAG5GD,oBAAiBF,SAASA;AAC1BE,oBAAiBG,eAAeZ;AAChCS,oBAAiBI,cAAcV,OAAOW;AACtCL,oBAAiBM,aAAaR,OAAOI;AACrCF,oBAAiBC,MAAMH,OAAOG;;AAEhC,SAAOP;;;;;;;;;;;;;;;;;;;;;;;;GC3JX,SAAgBc,OAAOC,MAAkBC,OAAiC;AACxE,SACEC,QACAC,YAAAA;AAEA,MAAIA,QAAQC,SAAS,SACnB,OAAM,IAAIC,MAAM,yDAAA;EAElB,MAAMC,WAAWR,oBAAoBI,QAAQC,QAAAA;AAE7CG,WAASC,QAAQP,QAAQC;AAEzB,SAAOC;;;;;;;;;;;;;;;;;;;;;;;;;GCbX,SAAgBO,SAASC,MAAY;AACnC,SACEC,QACAC,YAAAA;AAEA,MAAIA,QAAQC,SAAS,SACnB,OAAM,IAAIC,MACR,2DAAA;EAGJ,MAAMC,WAAWP,oBAAoBG,QAAQC,QAAAA;AAC7CG,WAASC,oBAAoBN;AAE7B,SAAOC;;;;;;;;;;;;;;;;;;;;;;;;GC4BX,SAAgBU,OACd,EACEC,cAAc,EAAE,EAChBC,UAAU,EAAE,EACZC,SAAS,EAAE,EACXC,YAAY,EAAE,EACdC,UACAC,aACiB;CACjBL,aAAa,EAAE;CACfC,SAAS,EAAE;CACXC,QAAQ,EAAE;CACVC,WAAW,EAAE;CACd,EAAA;AAED,SAAQG,QAAmBC,YAAAA;AACzB,MAAIA,QAAQC,SAAS,QACnB,OAAM,IAAIC,MAAM,0DAAA;EAGlB,MAAMC,QAAQb,eAAec,OAAOL,OAAAA;EACpC,MAAMM,iBAAiBd,kBAAkBQ,QAAQC,QAAAA;AACjD,OAAK,MAAMM,cAAcb,YACvBY,gBAAeZ,YAAYc,IAAID,WAAAA;AAEjC,OAAK,MAAME,kBAAkBd,QAC3BW,gBAAeX,QAAQa,IAAIC,eAAAA;AAE7B,OAAK,MAAMC,SAASC,MAAMC,KAAKhB,OAAAA,CAAQiB,SAAO,CAC5CP,gBAAeV,OAAOY,IAAIE,MAAAA;AAE5B,OAAK,MAAMI,YAAYjB,UACrBS,gBAAeT,UAAUW,IAAIM,SAAAA;AAG/B,SAAOzB,WAAW;GAChBe;GACAW,OAAOzB,gBAAgB0B;GACvBlB;GACAC;GACF,CAAA,CAAGC,QAAQC,QAAAA;;;;;;ACmBf,SAAgBkB,UAA0CC,UAEzD;AAmBC,SAAQC,QAAiBC,YAAAA;AACvB,MAAIA,QAAQC,SAAS,SACnB,OAAM,IAAIC,MACR,2DAAA;EAGJ,MAAMC,SAASL,SAASK;AACxB,MAAIH,QAAQI,UAAU;GACpB,IAAIC,mBAAmBV,oBACrBI,QACAC,QAAAA;AAEF,OAAIK,iBAAiBF,UAAUE,iBAAiBF,OAAOG,IACrD,OAAM,IAAIJ,MACR,qBAAqBC,OAAOI,OAAO,GAAGJ,OAAOG,IAAI,wDAAuD;AAG5GD,oBAAiBF,SAASA;AAC1BE,oBAAiBG,eAAeZ;AAChCS,oBAAiBI,cAAcV,OAAOW;AACtCL,oBAAiBM,aAAaR,OAAOI;AACrCF,oBAAiBC,MAAMH,OAAOG;;AAEhC,SAAOP;;;;;;ACrDX,SAAgBe,OAA2CC,UAE1D;AAcC,SAAQC,QAAiBC,YAAAA;AACvB,MAAIA,QAAQC,SAAS,SACnB,OAAM,IAAIC,MACR,2DAAA;EAGJ,MAAMC,SAASL,SAASK;AACxB,MAAIH,QAAQI,UAAU;GACpB,IAAIC,mBAAmBV,oBACrBI,QACAC,QAAAA;AAEF,OAAIK,iBAAiBF,UAAUE,iBAAiBF,OAAOG,IACrD,OAAM,IAAIJ,MACR,qBAAqBC,OAAOI,OAAO,GAAGJ,OAAOG,IAAI,wDAAuD;AAG5GD,oBAAiBF,SAASA;AAC1BE,oBAAiBG,eAAeZ;AAChCS,oBAAiBI,cAAcV,OAAOW;AACtCL,oBAAiBM,aAAaR,OAAOI;AACrCF,oBAAiBC,MAAMH,OAAOG;;AAEhC,SAAOP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GC9GX,SAAgBe,UACd,GAAGC,QAGA;AAEH,QAAO,SACLC,QACAC,SAA4D;AAE5D,MAAIA,QAAQC,SAAS,SAAS;GAC5B,MAAMC,qBAAqBP,sBACzBI,QACAC,QAAAA;AAEF,QAAK,MAAMG,SAASL,OAAOM,SAAO,CAChCF,oBAAmBJ,OAAOO,IAAIF,MAAAA;aAEvBH,QAAQC,SAAS,UAAU;GACpC,MAAMK,mBAAmBV,oBAAoBG,QAAQC,QAAAA;AACrD,QAAK,MAAMG,SAASL,OAAOM,SAAO,CAChCE,kBAAiBR,OAAOO,IAAIF,MAAAA;QAG9B,OAAM,IAAII,MACR,wEAAA;AAGJ,SAAOR"}
@@ -1,5 +1,5 @@
1
- const require_navios_factory = require('./navios.factory-CO5MB_OK.cjs');
2
- const require_tokens = require('./tokens-CWw9kyeD.cjs');
1
+ const require_navios_factory = require('./navios.factory-CUrO_p6K.cjs');
2
+ const require_tokens = require('./tokens-BEuBMGGX.cjs');
3
3
  let _navios_di = require("@navios/di");
4
4
 
5
5
  //#region src/metadata/handler.metadata.mts
@@ -45,21 +45,18 @@ function getEndpointMetadata(target, context) {
45
45
  //#region src/metadata/controller.metadata.mts
46
46
  const ControllerMetadataKey = Symbol("ControllerMetadataKey");
47
47
  function getControllerMetadata(target, context) {
48
- if (context.metadata) {
49
- const metadata = context.metadata[ControllerMetadataKey];
50
- if (metadata) return metadata;
51
- else {
52
- const newMetadata = {
53
- endpoints: getAllEndpointMetadata(context),
54
- guards: /* @__PURE__ */ new Set(),
55
- customAttributes: /* @__PURE__ */ new Map()
56
- };
57
- context.metadata[ControllerMetadataKey] = newMetadata;
58
- target[ControllerMetadataKey] = newMetadata;
59
- return newMetadata;
60
- }
61
- }
62
- throw new Error("[Navios] Wrong environment.");
48
+ if (!context.metadata) throw new Error("[Navios] Wrong environment.");
49
+ const existingMetadata = context.metadata[ControllerMetadataKey];
50
+ if (existingMetadata) return existingMetadata;
51
+ const newMetadata = {
52
+ name: target.name,
53
+ endpoints: getAllEndpointMetadata(context),
54
+ guards: /* @__PURE__ */ new Set(),
55
+ customAttributes: /* @__PURE__ */ new Map()
56
+ };
57
+ context.metadata[ControllerMetadataKey] = newMetadata;
58
+ target[ControllerMetadataKey] = newMetadata;
59
+ return newMetadata;
63
60
  }
64
61
  function extractControllerMetadata(target) {
65
62
  const metadata = target[ControllerMetadataKey];
@@ -444,4 +441,4 @@ Object.defineProperty(exports, 'hasManagedMetadata', {
444
441
  return hasManagedMetadata;
445
442
  }
446
443
  });
447
- //# sourceMappingURL=use-guards.decorator-C4ml9XaT.cjs.map
444
+ //# sourceMappingURL=use-guards.decorator-DhumFTk3.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-guards.decorator-DhumFTk3.cjs","names":["EndpointMetadataKey","Symbol","getAllEndpointMetadata","context","metadata","Set","Error","getEndpointMetadata","target","endpointMetadata","Array","from","find","item","classMethod","name","newMetadata","url","successStatusCode","adapterToken","headers","httpMethod","config","guards","customAttributes","Map","add","getAllEndpointMetadata","ControllerMetadataKey","Symbol","getControllerMetadata","target","context","metadata","Error","existingMetadata","newMetadata","name","endpoints","guards","Set","customAttributes","Map","extractControllerMetadata","hasControllerMetadata","NaviosManagedMetadataKey","Symbol","getManagedMetadata","target","hasManagedMetadata","Injectable","InjectionToken","getControllerMetadata","Controller","guards","registry","priority","scope","target","context","kind","Error","token","create","metadata","controllerMetadata","guard","Array","from","reverse","add","getEndpointMetadata","EndpointAdapterToken","Endpoint","endpoint","target","context","kind","Error","config","metadata","endpointMetadata","url","method","adapterToken","classMethod","name","httpMethod","getEndpointMetadata","Header","name","value","target","context","kind","Error","metadata","headers","getEndpointMetadata","HttpCode","code","target","context","kind","Error","metadata","successStatusCode","Injectable","InjectableScope","InjectionToken","getModuleMetadata","Module","controllers","imports","guards","overrides","priority","registry","target","context","kind","Error","token","create","moduleMetadata","controller","add","importedModule","guard","Array","from","reverse","override","scope","Singleton","getEndpointMetadata","MultipartAdapterToken","Multipart","endpoint","target","context","kind","Error","config","metadata","endpointMetadata","url","method","adapterToken","classMethod","name","httpMethod","getEndpointMetadata","StreamAdapterToken","Stream","endpoint","target","context","kind","Error","config","metadata","endpointMetadata","url","method","adapterToken","classMethod","name","httpMethod","getControllerMetadata","getEndpointMetadata","UseGuards","guards","target","context","kind","controllerMetadata","guard","reverse","add","endpointMetadata","Error"],"sources":["../src/metadata/handler.metadata.mts","../src/metadata/controller.metadata.mts","../src/metadata/navios-managed.metadata.mts","../src/decorators/controller.decorator.mts","../src/decorators/endpoint.decorator.mts","../src/decorators/header.decorator.mts","../src/decorators/http-code.decorator.mts","../src/decorators/module.decorator.mts","../src/decorators/multipart.decorator.mts","../src/decorators/stream.decorator.mts","../src/decorators/use-guards.decorator.mts"],"sourcesContent":["import type { HttpMethod } from '@navios/builder'\nimport type { ClassTypeWithInstance, InjectionToken } from '@navios/di'\n\nimport type {\n AbstractHttpHandlerAdapterInterface,\n CanActivate,\n HttpHeader,\n} from '../interfaces/index.mjs'\n\nexport const EndpointMetadataKey = Symbol('EndpointMetadataKey')\n\nexport interface HandlerMetadata<Config = null> {\n classMethod: string\n url: string\n successStatusCode: number\n adapterToken:\n | InjectionToken<AbstractHttpHandlerAdapterInterface, undefined>\n | ClassTypeWithInstance<AbstractHttpHandlerAdapterInterface>\n | null\n headers: Partial<Record<HttpHeader, number | string | string[] | undefined>>\n httpMethod: HttpMethod\n config: Config\n guards: Set<\n ClassTypeWithInstance<CanActivate> | InjectionToken<CanActivate, undefined>\n >\n customAttributes: Map<string | symbol, any>\n}\n\nexport function getAllEndpointMetadata(\n context: ClassMethodDecoratorContext | ClassDecoratorContext,\n): Set<HandlerMetadata<any>> {\n if (context.metadata) {\n const metadata = context.metadata[EndpointMetadataKey] as\n | Set<HandlerMetadata>\n | undefined\n if (metadata) {\n return metadata\n } else {\n context.metadata[EndpointMetadataKey] = new Set<HandlerMetadata<any>>()\n return context.metadata[EndpointMetadataKey] as Set<HandlerMetadata<any>>\n }\n }\n throw new Error('[Navios] Wrong environment.')\n}\n\nexport function getEndpointMetadata<Config = any>(\n target: Function,\n context: ClassMethodDecoratorContext,\n): HandlerMetadata<Config> {\n if (context.metadata) {\n const metadata = getAllEndpointMetadata(context)\n if (metadata) {\n const endpointMetadata = Array.from(metadata).find(\n (item) => item.classMethod === target.name,\n )\n if (endpointMetadata) {\n return endpointMetadata\n } else {\n const newMetadata: HandlerMetadata<Config> = {\n classMethod: target.name,\n url: '',\n successStatusCode: 200,\n adapterToken: null,\n headers: {},\n httpMethod: 'GET',\n // @ts-expect-error We are using a generic type here\n config: null,\n guards: new Set<\n | ClassTypeWithInstance<CanActivate>\n | InjectionToken<CanActivate, undefined>\n >(),\n customAttributes: new Map<string | symbol, any>(),\n }\n metadata.add(newMetadata)\n return newMetadata\n }\n }\n }\n throw new Error('[Navios] Wrong environment.')\n}\n","import type {\n ClassType,\n ClassTypeWithInstance,\n InjectionToken,\n} from '@navios/di'\n\nimport type { CanActivate } from '../interfaces/index.mjs'\nimport type { HandlerMetadata } from './handler.metadata.mjs'\n\nimport { getAllEndpointMetadata } from './handler.metadata.mjs'\n\nexport const ControllerMetadataKey = Symbol('ControllerMetadataKey')\n\nexport interface ControllerMetadata {\n /**\n * The name of the controller class.\n */\n name: string\n endpoints: Set<HandlerMetadata>\n guards: Set<\n ClassTypeWithInstance<CanActivate> | InjectionToken<CanActivate, undefined>\n >\n customAttributes: Map<string | symbol, any>\n}\n\nexport function getControllerMetadata(\n target: ClassType,\n context: ClassDecoratorContext,\n): ControllerMetadata {\n if (!context.metadata) {\n throw new Error('[Navios] Wrong environment.')\n }\n\n const existingMetadata = context.metadata[ControllerMetadataKey] as\n | ControllerMetadata\n | undefined\n\n if (existingMetadata) {\n return existingMetadata\n }\n\n const newMetadata: ControllerMetadata = {\n name: target.name,\n endpoints: getAllEndpointMetadata(context),\n guards: new Set<\n ClassTypeWithInstance<CanActivate> | InjectionToken<CanActivate, undefined>\n >(),\n customAttributes: new Map<string | symbol, any>(),\n }\n\n context.metadata[ControllerMetadataKey] = newMetadata\n // @ts-expect-error We add a custom metadata key to the target\n target[ControllerMetadataKey] = newMetadata\n\n return newMetadata\n}\n\nexport function extractControllerMetadata(\n target: ClassType,\n): ControllerMetadata {\n // @ts-expect-error We add a custom metadata key to the target\n const metadata = target[ControllerMetadataKey] as\n | ControllerMetadata\n | undefined\n if (!metadata) {\n throw new Error(\n '[Navios] Controller metadata not found. Make sure to use @Controller decorator.',\n )\n }\n return metadata\n}\n\nexport function hasControllerMetadata(target: ClassType): boolean {\n // @ts-expect-error We add a custom metadata key to the target\n const metadata = target[ControllerMetadataKey] as\n | ControllerMetadata\n | undefined\n return !!metadata\n}\n","import type { ClassType } from '@navios/di'\n\n/**\n * Symbol used to identify Navios-managed classes (Controller, Module, MessageController, etc.).\n * This allows AttributeFactory to work with any Navios-managed class type generically.\n */\nexport const NaviosManagedMetadataKey = Symbol('NaviosManagedMetadataKey')\n\n/**\n * Interface for metadata that has custom attributes.\n * Used by Navios-managed classes (Controller, Module, MessageController, etc.).\n */\nexport interface ManagedMetadata {\n customAttributes: Map<string | symbol, any>\n}\n\n/**\n * Gets managed metadata from a class if it exists.\n * This is a generic function that works with any Navios-managed class type.\n *\n * @param target - The class to check\n * @returns The metadata with customAttributes, or null if not managed\n */\nexport function getManagedMetadata(target: ClassType): ManagedMetadata | null {\n // @ts-expect-error - Checking for managed metadata key\n if (target[NaviosManagedMetadataKey]) {\n // @ts-expect-error - Accessing managed metadata\n return target[NaviosManagedMetadataKey] as ManagedMetadata\n }\n return null\n}\n\n/**\n * Checks if a class is Navios-managed (has managed metadata).\n *\n * @param target - The class to check\n * @returns true if the class is Navios-managed\n */\nexport function hasManagedMetadata(target: ClassType): boolean {\n return getManagedMetadata(target) !== null\n}\n\n","import type { ClassType, InjectableScope } from '@navios/di'\n\nimport { Injectable, InjectionToken, Registry } from '@navios/di'\n\nimport { getControllerMetadata } from '../metadata/index.mjs'\n\n/**\n * Options for configuring a Navios controller.\n */\nexport interface ControllerOptions {\n /**\n * Guards to apply to all endpoints in this controller.\n * Guards are executed in reverse order (last guard first).\n */\n guards?: ClassType[] | Set<ClassType>\n /**\n * Registry to use for the controller.\n * Registry is used to store the controller and its endpoints.\n */\n registry?: Registry\n /**\n * Priority to use for the controller.\n * Priority is used to sort the controller in the registry.\n */\n priority?: number\n /**\n * Scope to use for the controller.\n * Scope is used to determine the scope of the controller.\n */\n scope?: InjectableScope\n}\n\n/**\n * Decorator that marks a class as a Navios controller.\n *\n * Controllers handle HTTP requests and define endpoints.\n * They are request-scoped by default, meaning a new instance is created for each request.\n *\n * @param options - Controller configuration options\n * @returns A class decorator\n *\n * @example\n * ```typescript\n * @Controller({ guards: [AuthGuard] })\n * export class UserController {\n * @Endpoint(getUserEndpoint)\n * async getUser(request: EndpointParams<typeof getUserEndpoint>) {\n * // Handle request\n * }\n * }\n * ```\n */\nexport function Controller({\n guards,\n registry,\n priority,\n scope,\n}: ControllerOptions = {}) {\n return function (target: ClassType, context: ClassDecoratorContext) {\n if (context.kind !== 'class') {\n throw new Error(\n '[Navios] @Controller decorator can only be used on classes.',\n )\n }\n const token = InjectionToken.create(target)\n if (context.metadata) {\n const controllerMetadata = getControllerMetadata(target, context)\n if (guards) {\n for (const guard of Array.from(guards).reverse()) {\n controllerMetadata.guards.add(guard)\n }\n }\n }\n return Injectable({\n token,\n registry,\n priority,\n scope,\n })(target, context)\n }\n}\n","import type {\n EndpointHandler,\n EndpointOptions,\n RequestArgs,\n} from '@navios/builder'\nimport type { z } from 'zod/v4'\n\nimport { ZodDiscriminatedUnion } from 'zod/v4'\n\nimport { getEndpointMetadata } from '../metadata/index.mjs'\nimport { EndpointAdapterToken } from '../tokens/index.mjs'\n\n/**\n * Extracts the typed parameters for an endpoint handler function.\n *\n * This utility type extracts URL parameters, query parameters, and request body\n * from an endpoint declaration and flattens them into a single object.\n *\n * @typeParam EndpointDeclaration - The endpoint declaration from @navios/builder\n *\n * @example\n * ```typescript\n * const getUserEndpoint = api.declareEndpoint({\n * method: 'get',\n * url: '/users/$userId',\n * querySchema: z.object({ include: z.string().optional() }),\n * responseSchema: z.object({ id: z.string(), name: z.string() }),\n * })\n *\n * @Endpoint(getUserEndpoint)\n * async getUser(request: EndpointParams<typeof getUserEndpoint>) {\n * // request.urlParams.userId is typed as string\n * // request.query.include is typed as string | undefined\n * }\n * ```\n */\nexport type EndpointParams<\n EndpointDeclaration extends EndpointHandler<Config, false>,\n Config extends EndpointOptions = EndpointDeclaration['config'],\n> = RequestArgs<\n Config['url'],\n Config['querySchema'],\n Config['requestSchema'],\n Config['urlParamsSchema'],\n true\n>\n\n/**\n * Extracts the typed return value for an endpoint handler function.\n *\n * This utility type extracts the response schema from an endpoint declaration\n * and returns the appropriate Promise type.\n *\n * @typeParam EndpointDeclaration - The endpoint declaration from @navios/builder\n *\n * @example\n * ```typescript\n * const getUserEndpoint = api.declareEndpoint({\n * method: 'get',\n * url: '/users/$userId',\n * responseSchema: z.object({ id: z.string(), name: z.string() }),\n * })\n *\n * @Endpoint(getUserEndpoint)\n * async getUser(request: EndpointParams<typeof getUserEndpoint>): EndpointResult<typeof getUserEndpoint> {\n * return { id: '1', name: 'John' } // Type-checked against responseSchema\n * }\n * ```\n */\nexport type EndpointResult<\n EndpointDeclaration extends {\n config: EndpointOptions\n },\n> =\n EndpointDeclaration['config']['responseSchema'] extends ZodDiscriminatedUnion<\n infer Options\n >\n ? Promise<z.input<Options[number]>>\n : Promise<z.input<EndpointDeclaration['config']['responseSchema']>>\n\n/**\n * Decorator that marks a method as an HTTP endpoint.\n *\n * The endpoint must be defined using @navios/builder's `declareEndpoint` method.\n * This ensures type safety and consistency between client and server.\n *\n * @param endpoint - The endpoint declaration from @navios/builder\n * @returns A method decorator\n *\n * @example\n * ```typescript\n * import { builder } from '@navios/builder'\n *\n * const api = builder()\n * const getUserEndpoint = api.declareEndpoint({\n * method: 'get',\n * url: '/users/$userId',\n * responseSchema: z.object({ id: z.string(), name: z.string() }),\n * })\n *\n * @Controller()\n * export class UserController {\n * @Endpoint(getUserEndpoint)\n * async getUser(request: EndpointParams<typeof getUserEndpoint>) {\n * const { userId } = request.urlParams\n * return { id: userId, name: 'John' }\n * }\n * }\n * ```\n */\nexport function Endpoint<const Config extends EndpointOptions>(\n endpoint: EndpointHandler<Config, false>,\n): (\n target: (\n params: RequestArgs<\n Config['url'],\n Config['querySchema'],\n Config['requestSchema'],\n Config['urlParamsSchema'],\n true\n >,\n ) =>\n | Promise<z.input<Config['responseSchema']>>\n | z.input<Config['responseSchema']>,\n context: ClassMethodDecoratorContext,\n) => void\nexport function Endpoint<const Config extends EndpointOptions>(\n endpoint: EndpointHandler<Config, false>,\n): (\n target: () =>\n | Promise<z.input<Config['responseSchema']>>\n | z.input<Config['responseSchema']>,\n context: ClassMethodDecoratorContext,\n) => void\nexport function Endpoint<const Config extends EndpointOptions>(\n endpoint: EndpointHandler<Config, false>,\n) {\n type Params = RequestArgs<\n Config['url'],\n Config['querySchema'],\n Config['requestSchema'],\n Config['urlParamsSchema'],\n true\n >\n\n type Handler =\n | ((\n params: Params,\n ) =>\n | Promise<z.input<Config['responseSchema']>>\n | z.input<Config['responseSchema']>)\n | (() =>\n | Promise<z.input<Config['responseSchema']>>\n | z.input<Config['responseSchema']>)\n\n return (target: Handler, context: ClassMethodDecoratorContext) => {\n if (context.kind !== 'method') {\n throw new Error(\n '[Navios] Endpoint decorator can only be used on methods.',\n )\n }\n const config = endpoint.config\n if (context.metadata) {\n let endpointMetadata = getEndpointMetadata<EndpointOptions>(\n target,\n context,\n )\n if (endpointMetadata.config && endpointMetadata.config.url) {\n throw new Error(\n `[Navios] Endpoint ${config.method} ${config.url} already exists. Please use a different method or url.`,\n )\n }\n endpointMetadata.config = config\n endpointMetadata.adapterToken = EndpointAdapterToken\n endpointMetadata.classMethod = target.name\n endpointMetadata.httpMethod = config.method\n endpointMetadata.url = config.url\n }\n return target\n }\n}\n","import type { HttpHeader } from '../interfaces/index.mjs'\n\nimport { getEndpointMetadata } from '../metadata/index.mjs'\n\n/**\n * Decorator that sets a custom HTTP response header for an endpoint.\n * \n * @param name - The header name (e.g., 'Content-Type', 'Cache-Control')\n * @param value - The header value (string, number, or array of strings)\n * @returns A method decorator\n * \n * @example\n * ```typescript\n * @Controller()\n * export class UserController {\n * @Endpoint(getUserEndpoint)\n * @Header('Cache-Control', 'max-age=3600')\n * async getUser() {\n * return { id: '1', name: 'John' }\n * }\n * }\n * ```\n */\nexport function Header(name: HttpHeader, value: string | number | string[]) {\n return <T extends Function>(\n target: T,\n context: ClassMethodDecoratorContext,\n ) => {\n if (context.kind !== 'method') {\n throw new Error('[Navios] Header decorator can only be used on methods.')\n }\n const metadata = getEndpointMetadata(target, context)\n\n metadata.headers[name] = value\n\n return target\n }\n}\n","import { getEndpointMetadata } from '../metadata/index.mjs'\n\n/**\n * Decorator that sets a custom HTTP status code for successful responses.\n * \n * By default, endpoints return 200 OK. Use this decorator to return a different status code.\n * \n * @param code - The HTTP status code to return (e.g., 201, 204, 202)\n * @returns A method decorator\n * \n * @example\n * ```typescript\n * @Controller()\n * export class UserController {\n * @Endpoint(createUserEndpoint)\n * @HttpCode(201)\n * async createUser() {\n * return { id: '1', name: 'John' }\n * }\n * }\n * ```\n */\nexport function HttpCode(code: number) {\n return <T extends Function>(\n target: T,\n context: ClassMethodDecoratorContext,\n ) => {\n if (context.kind !== 'method') {\n throw new Error(\n '[Navios] HttpCode decorator can only be used on methods.',\n )\n }\n const metadata = getEndpointMetadata(target, context)\n metadata.successStatusCode = code\n\n return target\n }\n}\n","import type { ClassType, Registry } from '@navios/di'\n\nimport { Injectable, InjectableScope, InjectionToken } from '@navios/di'\n\nimport { getModuleMetadata } from '../metadata/index.mjs'\n\n/**\n * Options for configuring a Navios module.\n */\nexport interface ModuleOptions {\n /**\n * Controllers to register in this module.\n * Controllers handle HTTP requests and define endpoints.\n */\n controllers?: ClassType[] | Set<ClassType>\n /**\n * Other modules to import into this module.\n * Imported modules' controllers and services become available.\n */\n imports?: ClassType[] | Set<ClassType>\n /**\n * Guards to apply to all controllers in this module.\n * Guards are executed in reverse order (last guard first).\n */\n guards?: ClassType[] | Set<ClassType>\n /**\n * Service override classes to import for side effects.\n * These classes are imported to ensure their @Injectable decorators execute,\n * allowing them to register with the DI system. Overrides should use the same\n * InjectionToken as the original service with a higher priority.\n */\n overrides?: ClassType[] | Set<ClassType>\n /**\n * Priority to use for the module.\n * Priority is used to sort the module in the registry.\n */\n priority?: number\n /**\n * Registry to use for the module.\n * Registry is used to store the module and its controllers.\n */\n registry?: Registry\n}\n\n/**\n * Decorator that marks a class as a Navios module.\n *\n * Modules are the basic building blocks of a Navios application.\n * They organize controllers, services, and other modules into logical units.\n *\n * @param options - Module configuration options\n * @returns A class decorator\n *\n * @example\n * ```typescript\n * @Module({\n * controllers: [UserController, AuthController],\n * imports: [DatabaseModule],\n * guards: [AuthGuard],\n * })\n * export class AppModule {}\n * ```\n */\nexport function Module(\n {\n controllers = [],\n imports = [],\n guards = [],\n overrides = [],\n priority,\n registry,\n }: ModuleOptions = {\n controllers: [],\n imports: [],\n guards: [],\n overrides: [],\n },\n) {\n return (target: ClassType, context: ClassDecoratorContext) => {\n if (context.kind !== 'class') {\n throw new Error('[Navios] @Module decorator can only be used on classes.')\n }\n // Register the module in the service locator\n const token = InjectionToken.create(target)\n const moduleMetadata = getModuleMetadata(target, context)\n for (const controller of controllers) {\n moduleMetadata.controllers.add(controller)\n }\n for (const importedModule of imports) {\n moduleMetadata.imports.add(importedModule)\n }\n for (const guard of Array.from(guards).reverse()) {\n moduleMetadata.guards.add(guard)\n }\n for (const override of overrides) {\n moduleMetadata.overrides.add(override)\n }\n\n return Injectable({\n token,\n scope: InjectableScope.Singleton,\n priority,\n registry,\n })(target, context)\n }\n}\n","import type { EndpointOptions, RequestArgs } from '@navios/builder'\nimport type { z, ZodObject, ZodType } from 'zod/v4'\n\nimport { ZodDiscriminatedUnion } from 'zod/v4'\n\nimport { getEndpointMetadata } from '../metadata/index.mjs'\nimport { MultipartAdapterToken } from '../tokens/index.mjs'\n\n/**\n * Extracts the typed parameters for a multipart endpoint handler function.\n *\n * Similar to `EndpointParams`, but specifically for multipart/form-data endpoints.\n *\n * @typeParam EndpointDeclaration - The endpoint declaration from @navios/builder\n */\nexport type MultipartParams<\n EndpointDeclaration extends {\n config: EndpointOptions\n },\n Url extends string = EndpointDeclaration['config']['url'],\n QuerySchema = EndpointDeclaration['config']['querySchema'],\n> = QuerySchema extends ZodObject\n ? EndpointDeclaration['config']['requestSchema'] extends ZodType\n ? RequestArgs<\n Url,\n QuerySchema,\n EndpointDeclaration['config']['requestSchema'],\n EndpointDeclaration['config']['urlParamsSchema'],\n true\n >\n : RequestArgs<\n Url,\n QuerySchema,\n undefined,\n EndpointDeclaration['config']['urlParamsSchema'],\n true\n >\n : EndpointDeclaration['config']['requestSchema'] extends ZodType\n ? RequestArgs<\n Url,\n undefined,\n EndpointDeclaration['config']['requestSchema'],\n EndpointDeclaration['config']['urlParamsSchema'],\n true\n >\n : RequestArgs<\n Url,\n undefined,\n undefined,\n EndpointDeclaration['config']['urlParamsSchema'],\n true\n >\n\n/**\n * Extracts the typed return value for a multipart endpoint handler function.\n *\n * @typeParam EndpointDeclaration - The endpoint declaration from @navios/builder\n */\nexport type MultipartResult<\n EndpointDeclaration extends {\n config: EndpointOptions\n },\n> =\n EndpointDeclaration['config']['responseSchema'] extends ZodDiscriminatedUnion<\n infer Options\n >\n ? Promise<z.input<Options[number]>>\n : Promise<z.input<EndpointDeclaration['config']['responseSchema']>>\n\n/**\n * Decorator that marks a method as a multipart/form-data endpoint.\n *\n * Use this decorator for endpoints that handle file uploads or form data.\n * The endpoint must be defined using @navios/builder's `declareMultipart` method.\n *\n * @param endpoint - The multipart endpoint declaration from @navios/builder\n * @returns A method decorator\n *\n * @example\n * ```typescript\n * const uploadFileEndpoint = api.declareMultipart({\n * method: 'post',\n * url: '/upload',\n * requestSchema: z.object({ file: z.instanceof(File) }),\n * responseSchema: z.object({ url: z.string() }),\n * })\n *\n * @Controller()\n * export class FileController {\n * @Multipart(uploadFileEndpoint)\n * async uploadFile(request: MultipartParams<typeof uploadFileEndpoint>) {\n * const { file } = request.data\n * // Handle file upload\n * return { url: 'https://example.com/file.jpg' }\n * }\n * }\n * ```\n */\nexport function Multipart<Config extends EndpointOptions>(endpoint: {\n config: Config\n}): (\n target: (\n params: RequestArgs<\n Config['url'],\n Config['querySchema'],\n Config['requestSchema'],\n Config['urlParamsSchema'],\n true\n >,\n ) =>\n | Promise<z.input<Config['responseSchema']>>\n | z.input<Config['responseSchema']>,\n context: ClassMethodDecoratorContext,\n) => void\nexport function Multipart<Config extends EndpointOptions>(endpoint: {\n config: Config\n}): (\n target: () =>\n | Promise<z.input<Config['responseSchema']>>\n | z.input<Config['responseSchema']>,\n context: ClassMethodDecoratorContext,\n) => void\nexport function Multipart<Config extends EndpointOptions>(endpoint: {\n config: Config\n}) {\n type Params = RequestArgs<\n Config['url'],\n Config['querySchema'],\n Config['requestSchema'],\n Config['urlParamsSchema'],\n true\n >\n\n type Handler =\n | ((\n params: Params,\n ) =>\n | Promise<z.input<Config['responseSchema']>>\n | z.input<Config['responseSchema']>)\n | (() =>\n | Promise<z.input<Config['responseSchema']>>\n | z.input<Config['responseSchema']>)\n\n return (target: Handler, context: ClassMethodDecoratorContext) => {\n if (context.kind !== 'method') {\n throw new Error(\n '[Navios] Endpoint decorator can only be used on methods.',\n )\n }\n const config = endpoint.config\n if (context.metadata) {\n let endpointMetadata = getEndpointMetadata<EndpointOptions>(\n target,\n context,\n )\n if (endpointMetadata.config && endpointMetadata.config.url) {\n throw new Error(\n `[Navios] Endpoint ${config.method} ${config.url} already exists. Please use a different method or url.`,\n )\n }\n endpointMetadata.config = config\n endpointMetadata.adapterToken = MultipartAdapterToken\n endpointMetadata.classMethod = target.name\n endpointMetadata.httpMethod = config.method\n endpointMetadata.url = config.url\n }\n return target\n }\n}\n","import type {\n BaseEndpointOptions,\n RequestArgs,\n StreamHandler,\n} from '@navios/builder'\nimport type { ZodObject, ZodType } from 'zod/v4'\n\nimport { getEndpointMetadata } from '../metadata/index.mjs'\nimport { StreamAdapterToken } from '../tokens/index.mjs'\n\n/**\n * Extracts the typed parameters for a stream endpoint handler function.\n *\n * Similar to `EndpointParams`, but specifically for streaming endpoints.\n *\n * @typeParam EndpointDeclaration - The stream endpoint declaration from @navios/builder\n */\nexport type StreamParams<\n EndpointDeclaration extends StreamHandler<Config, false>,\n Config extends BaseEndpointOptions = EndpointDeclaration['config'],\n Url extends string = EndpointDeclaration['config']['url'],\n QuerySchema = EndpointDeclaration['config']['querySchema'],\n> = QuerySchema extends ZodObject\n ? EndpointDeclaration['config']['requestSchema'] extends ZodType\n ? RequestArgs<\n Url,\n QuerySchema,\n EndpointDeclaration['config']['requestSchema'],\n EndpointDeclaration['config']['urlParamsSchema'],\n true\n >\n : RequestArgs<\n Url,\n QuerySchema,\n undefined,\n EndpointDeclaration['config']['urlParamsSchema'],\n true\n >\n : EndpointDeclaration['config']['requestSchema'] extends ZodType\n ? RequestArgs<\n Url,\n undefined,\n EndpointDeclaration['config']['requestSchema'],\n EndpointDeclaration['config']['urlParamsSchema'],\n true\n >\n : RequestArgs<\n Url,\n undefined,\n undefined,\n EndpointDeclaration['config']['urlParamsSchema'],\n true\n >\n\n/**\n * Decorator that marks a method as a streaming endpoint.\n *\n * Use this decorator for endpoints that stream data (e.g., file downloads, SSE).\n * The endpoint must be defined using @navios/builder's `declareStream` method.\n *\n * @param endpoint - The stream endpoint declaration from @navios/builder\n * @returns A method decorator\n *\n * @example\n * ```typescript\n * const downloadFileEndpoint = api.declareStream({\n * method: 'get',\n * url: '/files/$fileId',\n * })\n *\n * @Controller()\n * export class FileController {\n * @Stream(downloadFileEndpoint)\n * async downloadFile(request: StreamParams<typeof downloadFileEndpoint>, reply: any) {\n * const { fileId } = request.urlParams\n * // Stream file data to reply\n * }\n * }\n * ```\n */\nexport function Stream<Config extends BaseEndpointOptions>(endpoint: {\n config: Config\n}): (\n target: (\n params: RequestArgs<\n Config['url'],\n Config['querySchema'],\n Config['requestSchema'],\n Config['urlParamsSchema'],\n true\n >,\n reply: any,\n ) => any,\n context: ClassMethodDecoratorContext,\n) => void\n// Bun doesn't support reply parameter\nexport function Stream<Config extends BaseEndpointOptions>(endpoint: {\n config: Config\n}): (\n target: (\n params: RequestArgs<\n Config['url'],\n Config['querySchema'],\n Config['requestSchema'],\n Config['urlParamsSchema'],\n true\n >,\n ) => any,\n context: ClassMethodDecoratorContext,\n) => void\nexport function Stream<Config extends BaseEndpointOptions>(endpoint: {\n config: Config\n}): (target: () => any, context: ClassMethodDecoratorContext) => void\nexport function Stream<Config extends BaseEndpointOptions>(endpoint: {\n config: Config\n}) {\n type Params = RequestArgs<\n Config['url'],\n Config['querySchema'],\n Config['requestSchema'],\n Config['urlParamsSchema'],\n true\n >\n\n type Handler =\n | ((params: Params, reply: any) => any)\n | ((params: Params) => any)\n | (() => any)\n\n return (target: Handler, context: ClassMethodDecoratorContext) => {\n if (context.kind !== 'method') {\n throw new Error(\n '[Navios] Endpoint decorator can only be used on methods.',\n )\n }\n const config = endpoint.config\n if (context.metadata) {\n let endpointMetadata = getEndpointMetadata<BaseEndpointOptions>(\n target,\n context,\n )\n if (endpointMetadata.config && endpointMetadata.config.url) {\n throw new Error(\n `[Navios] Endpoint ${config.method} ${config.url} already exists. Please use a different method or url.`,\n )\n }\n endpointMetadata.config = config\n endpointMetadata.adapterToken = StreamAdapterToken\n endpointMetadata.classMethod = target.name\n endpointMetadata.httpMethod = config.method\n endpointMetadata.url = config.url\n }\n return target\n }\n}\n","import type {\n ClassType,\n ClassTypeWithInstance,\n InjectionToken,\n} from '@navios/di'\n\nimport type { CanActivate } from '../interfaces/index.mjs'\n\nimport {\n getControllerMetadata,\n getEndpointMetadata,\n} from '../metadata/index.mjs'\n\n/**\n * Decorator that applies guards to a controller or endpoint.\n * \n * Guards are used for authentication, authorization, and request validation.\n * They implement the `CanActivate` interface and are executed before the endpoint handler.\n * Guards can be applied at the module, controller, or endpoint level.\n * \n * @param guards - Guard classes or injection tokens to apply\n * @returns A class or method decorator\n * \n * @example\n * ```typescript\n * // Apply to a controller\n * @Controller()\n * @UseGuards(AuthGuard, RoleGuard)\n * export class UserController {\n * @Endpoint(getUserEndpoint)\n * async getUser() { }\n * }\n * \n * // Apply to a specific endpoint\n * @Controller()\n * export class UserController {\n * @Endpoint(getUserEndpoint)\n * @UseGuards(AuthGuard)\n * async getUser() { }\n * }\n * ```\n */\nexport function UseGuards(\n ...guards: (\n | ClassTypeWithInstance<CanActivate>\n | InjectionToken<CanActivate, undefined>\n )[]\n) {\n return function <T extends Function>(\n target: T,\n context: ClassMethodDecoratorContext | ClassDecoratorContext,\n ): T {\n if (context.kind === 'class') {\n const controllerMetadata = getControllerMetadata(\n target as unknown as ClassType,\n context,\n )\n for (const guard of guards.reverse()) {\n controllerMetadata.guards.add(guard)\n }\n } else if (context.kind === 'method') {\n const endpointMetadata = getEndpointMetadata(target, context)\n for (const guard of guards.reverse()) {\n endpointMetadata.guards.add(guard)\n }\n } else {\n throw new Error(\n '[Navios] @UseGuards decorator can only be used on classes or methods.',\n )\n }\n return target\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@navios/core",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "author": {
5
5
  "name": "Oleksandr Hanzha",
6
6
  "email": "alex@granted.name"
@@ -56,7 +56,7 @@
56
56
  "supertest": "^7.1.4",
57
57
  "tsx": "^4.21.0",
58
58
  "typescript": "^5.9.3",
59
- "zod": "^4.2.1"
59
+ "zod": "^4.3.5"
60
60
  },
61
61
  "dependencies": {
62
62
  "@navios/di": "^1.0.0"
@@ -8,4 +8,7 @@ export * from './abstract-http-listen-options.interface.mjs'
8
8
  export * from './can-activate.mjs'
9
9
  export * from './http-header.mjs'
10
10
  export * from './navios-module.mjs'
11
+ export * from './plugin-stage.mjs'
12
+ export * from './plugin-context.mjs'
13
+ export * from './staged-plugin.interface.mjs'
11
14
  export * from './plugin.interface.mjs'
@@ -0,0 +1,104 @@
1
+ import type { Container } from '@navios/di'
2
+
3
+ import type { ModuleMetadata } from '../metadata/index.mjs'
4
+ import type { ModuleLoaderService } from '../services/module-loader.service.mjs'
5
+ import type { AbstractAdapterInterface } from './abstract-adapter.interface.mjs'
6
+ import type { PluginStage } from './plugin-stage.mjs'
7
+
8
+ /**
9
+ * Container-only context available at early stages.
10
+ * Available at: pre:modules-traverse
11
+ */
12
+ export interface ContainerOnlyContext {
13
+ /**
14
+ * The dependency injection container.
15
+ */
16
+ container: Container
17
+ }
18
+
19
+ /**
20
+ * Context with modules loaded.
21
+ * Available at: post:modules-traverse, pre:adapter-resolve
22
+ */
23
+ export interface ModulesLoadedContext extends ContainerOnlyContext {
24
+ /**
25
+ * All loaded modules with their metadata.
26
+ * Keys are module class names, values are their metadata.
27
+ */
28
+ modules: Map<string, ModuleMetadata>
29
+
30
+ /**
31
+ * Module loader service for extending the module tree.
32
+ * Use `moduleLoader.extendModules()` to add controllers dynamically.
33
+ */
34
+ moduleLoader: ModuleLoaderService
35
+ }
36
+
37
+ /**
38
+ * Full context with adapter available.
39
+ * Available at: post:adapter-resolve and all later stages
40
+ *
41
+ * @typeParam TAdapter - The adapter type, defaults to AbstractAdapterInterface
42
+ */
43
+ export interface FullPluginContext<
44
+ TAdapter extends AbstractAdapterInterface = AbstractAdapterInterface,
45
+ > extends ModulesLoadedContext {
46
+ /**
47
+ * The current adapter instance.
48
+ * Use type guards or cast to adapter-specific types for HTTP methods.
49
+ */
50
+ adapter: TAdapter
51
+ }
52
+
53
+ /**
54
+ * Maps each plugin stage to its available context type.
55
+ *
56
+ * @typeParam TAdapter - The adapter type for stages that have adapter access
57
+ */
58
+ export interface PluginStageContextMap<
59
+ TAdapter extends AbstractAdapterInterface = AbstractAdapterInterface,
60
+ > {
61
+ 'pre:modules-traverse': ContainerOnlyContext
62
+ 'post:modules-traverse': ModulesLoadedContext
63
+ 'pre:adapter-resolve': ModulesLoadedContext
64
+ 'post:adapter-resolve': FullPluginContext<TAdapter>
65
+ 'pre:adapter-setup': FullPluginContext<TAdapter>
66
+ 'post:adapter-setup': FullPluginContext<TAdapter>
67
+ 'pre:modules-init': FullPluginContext<TAdapter>
68
+ 'post:modules-init': FullPluginContext<TAdapter>
69
+ 'pre:ready': FullPluginContext<TAdapter>
70
+ 'post:ready': FullPluginContext<TAdapter>
71
+ }
72
+
73
+ /**
74
+ * Helper type to get the context type for a specific stage.
75
+ *
76
+ * @typeParam S - The plugin stage
77
+ * @typeParam TAdapter - The adapter type for stages that have adapter access
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * type MyContext = ContextForStage<'pre:adapter-resolve'>
82
+ * // MyContext is ModulesLoadedContext (no adapter)
83
+ *
84
+ * type FullContext = ContextForStage<'post:modules-init', BunApplicationService>
85
+ * // FullContext has typed adapter
86
+ * ```
87
+ */
88
+ export type ContextForStage<
89
+ S extends PluginStage,
90
+ TAdapter extends AbstractAdapterInterface = AbstractAdapterInterface,
91
+ > = PluginStageContextMap<TAdapter>[S]
92
+
93
+ /**
94
+ * Context provided to plugins during registration.
95
+ *
96
+ * @deprecated Use stage-specific context types (ContainerOnlyContext,
97
+ * ModulesLoadedContext, FullPluginContext) for better type safety.
98
+ * This is an alias for FullPluginContext for backward compatibility.
99
+ *
100
+ * @typeParam TAdapter - The adapter type, defaults to AbstractAdapterInterface
101
+ */
102
+ export type PluginContext<
103
+ TAdapter extends AbstractAdapterInterface = AbstractAdapterInterface,
104
+ > = FullPluginContext<TAdapter>
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Base stage names (without pre:/post: prefix)
3
+ */
4
+ export const PluginStageBase = {
5
+ MODULES_TRAVERSE: 'modules-traverse',
6
+ ADAPTER_RESOLVE: 'adapter-resolve',
7
+ ADAPTER_SETUP: 'adapter-setup',
8
+ MODULES_INIT: 'modules-init',
9
+ READY: 'ready',
10
+ } as const
11
+
12
+ export type PluginStageBase =
13
+ (typeof PluginStageBase)[keyof typeof PluginStageBase]
14
+
15
+ /**
16
+ * Full stage names with pre:/post: prefix
17
+ */
18
+ export type PluginStage = `pre:${PluginStageBase}` | `post:${PluginStageBase}`
19
+
20
+ /**
21
+ * Helper to create pre stage name from base
22
+ */
23
+ export const preStage = <T extends PluginStageBase>(base: T): `pre:${T}` =>
24
+ `pre:${base}`
25
+
26
+ /**
27
+ * Helper to create post stage name from base
28
+ */
29
+ export const postStage = <T extends PluginStageBase>(base: T): `post:${T}` =>
30
+ `post:${base}`
31
+
32
+ /**
33
+ * All stages as constants for direct access
34
+ */
35
+ export const PluginStages = {
36
+ PRE_MODULES_TRAVERSE: 'pre:modules-traverse',
37
+ POST_MODULES_TRAVERSE: 'post:modules-traverse',
38
+ PRE_ADAPTER_RESOLVE: 'pre:adapter-resolve',
39
+ POST_ADAPTER_RESOLVE: 'post:adapter-resolve',
40
+ PRE_ADAPTER_SETUP: 'pre:adapter-setup',
41
+ POST_ADAPTER_SETUP: 'post:adapter-setup',
42
+ PRE_MODULES_INIT: 'pre:modules-init',
43
+ POST_MODULES_INIT: 'post:modules-init',
44
+ PRE_READY: 'pre:ready',
45
+ POST_READY: 'post:ready',
46
+ } as const satisfies Record<string, PluginStage>
47
+
48
+ /**
49
+ * All stages in execution order
50
+ */
51
+ export const PLUGIN_STAGES_ORDER: readonly PluginStage[] = [
52
+ PluginStages.PRE_MODULES_TRAVERSE,
53
+ PluginStages.POST_MODULES_TRAVERSE,
54
+ PluginStages.PRE_ADAPTER_RESOLVE,
55
+ PluginStages.POST_ADAPTER_RESOLVE,
56
+ PluginStages.PRE_ADAPTER_SETUP,
57
+ PluginStages.POST_ADAPTER_SETUP,
58
+ PluginStages.PRE_MODULES_INIT,
59
+ PluginStages.POST_MODULES_INIT,
60
+ PluginStages.PRE_READY,
61
+ PluginStages.POST_READY,
62
+ ] as const
@@ -1,61 +1,17 @@
1
- import type { Container } from '@navios/di'
2
-
3
- import type { ModuleMetadata } from '../metadata/index.mjs'
4
- import type { ModuleLoaderService } from '../services/module-loader.service.mjs'
5
1
  import type { AbstractAdapterInterface } from './abstract-adapter.interface.mjs'
2
+ import type { FullPluginContext, PluginContext } from './plugin-context.mjs'
3
+ import type { PluginStage } from './plugin-stage.mjs'
4
+ import type { StagedPluginDefinition } from './staged-plugin.interface.mjs'
6
5
 
7
- /**
8
- * Context provided to plugins during registration.
9
- *
10
- * This context gives plugins access to the application's modules,
11
- * adapter instance, DI container, and module loader.
12
- *
13
- * @typeParam TAdapter - The adapter type, defaults to AbstractAdapterInterface
14
- *
15
- * @example
16
- * ```typescript
17
- * // Generic plugin that works with any adapter
18
- * async register(context: PluginContext) {
19
- * const modules = context.modules
20
- * // ...
21
- * }
22
- *
23
- * // Adapter-specific plugin with typed adapter
24
- * async register(context: PluginContext<BunApplicationService>) {
25
- * const server = context.adapter.getServer() // Typed as Bun.Server
26
- * // ...
27
- * }
28
- * ```
29
- */
30
- export interface PluginContext<
31
- TAdapter extends AbstractAdapterInterface = AbstractAdapterInterface,
32
- > {
33
- /**
34
- * All loaded modules with their metadata.
35
- * Keys are module class names, values are their metadata.
36
- */
37
- modules: Map<string, ModuleMetadata>
38
-
39
- /**
40
- * The current adapter instance.
41
- * Use type guards or cast to adapter-specific types for HTTP methods.
42
- */
43
- adapter: TAdapter
44
-
45
- /**
46
- * The dependency injection container.
47
- */
48
- container: Container
49
-
50
- /**
51
- * Module loader service for extending the module tree.
52
- * Use `moduleLoader.extendModules()` to add controllers dynamically.
53
- */
54
- moduleLoader: ModuleLoaderService
55
- }
6
+ // Re-export context types for backward compatibility
7
+ export type { PluginContext, FullPluginContext }
56
8
 
57
9
  /**
58
- * Base interface for Navios plugins.
10
+ * Base interface for Navios plugins (legacy).
11
+ *
12
+ * @deprecated Use staged plugins with explicit stage property instead.
13
+ * This interface maps to the `post:modules-init` stage.
14
+ * See `StagedPlugin` for the new pattern.
59
15
  *
60
16
  * Plugins are registered using `app.usePlugin()` and are initialized
61
17
  * after all modules are loaded but before the server starts listening.
@@ -65,7 +21,7 @@ export interface PluginContext<
65
21
  *
66
22
  * @example
67
23
  * ```typescript
68
- * // Generic plugin
24
+ * // Legacy pattern (still works, maps to post:modules-init)
69
25
  * const myPlugin: NaviosPlugin<{ enabled: boolean }> = {
70
26
  * name: 'my-plugin',
71
27
  * register: async (context, options) => {
@@ -75,13 +31,15 @@ export interface PluginContext<
75
31
  * },
76
32
  * }
77
33
  *
78
- * // Adapter-specific plugin
79
- * const fastifyPlugin: NaviosPlugin<Options, FastifyApplicationService> = {
80
- * name: 'fastify-plugin',
81
- * register: async (context, options) => {
82
- * const fastify = context.adapter.getServer() // Typed!
34
+ * // New pattern (recommended)
35
+ * import { definePostModulesInitPlugin } from '@navios/core'
36
+ *
37
+ * export const defineMyPlugin = definePostModulesInitPlugin()({
38
+ * name: 'my-plugin',
39
+ * register: async (context, options: { enabled: boolean }) => {
40
+ * // ...
83
41
  * },
84
- * }
42
+ * })
85
43
  * ```
86
44
  */
87
45
  export interface NaviosPlugin<
@@ -98,6 +56,7 @@ export interface NaviosPlugin<
98
56
  *
99
57
  * @param context - The plugin context with access to modules and adapter
100
58
  * @param options - Plugin-specific configuration options
59
+ * @deprecated Use staged plugins with explicit stage property
101
60
  */
102
61
  register(
103
62
  context: PluginContext<TAdapter>,
@@ -108,19 +67,29 @@ export interface NaviosPlugin<
108
67
  /**
109
68
  * Plugin definition combining a plugin with its options.
110
69
  *
111
- * This is the type returned by plugin factory functions like `defineOpenApiPlugin()`.
70
+ * @deprecated Use `StagedPluginDefinition` for new plugins.
71
+ * This type is kept for backward compatibility with legacy plugins.
112
72
  *
113
73
  * @typeParam TOptions - The type of options the plugin accepts
114
74
  * @typeParam TAdapter - The adapter type the plugin requires
115
75
  *
116
76
  * @example
117
77
  * ```typescript
78
+ * // Legacy pattern
118
79
  * function defineMyPlugin(options: MyPluginOptions): PluginDefinition<MyPluginOptions> {
119
80
  * return {
120
81
  * plugin: myPlugin,
121
82
  * options,
122
83
  * }
123
84
  * }
85
+ *
86
+ * // New pattern (recommended)
87
+ * import { definePostModulesInitPlugin } from '@navios/core'
88
+ *
89
+ * export const defineMyPlugin = definePostModulesInitPlugin()({
90
+ * name: 'my-plugin',
91
+ * register: (context, options: MyPluginOptions) => { ... },
92
+ * })
124
93
  * ```
125
94
  */
126
95
  export interface PluginDefinition<
@@ -137,3 +106,14 @@ export interface PluginDefinition<
137
106
  */
138
107
  options: TOptions
139
108
  }
109
+
110
+ /**
111
+ * Union of legacy and staged plugin definitions.
112
+ * Used internally by `usePlugin()` to accept both patterns.
113
+ */
114
+ export type AnyPluginDefinition<
115
+ TOptions = unknown,
116
+ TAdapter extends AbstractAdapterInterface = AbstractAdapterInterface,
117
+ > =
118
+ | PluginDefinition<TOptions, TAdapter>
119
+ | StagedPluginDefinition<PluginStage, TOptions, TAdapter>