@veloxts/router 0.7.8 → 0.7.9

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # @veloxts/router
2
2
 
3
+ ## 0.7.9
4
+
5
+ ### Patch Changes
6
+
7
+ - feat(router): swagger auto-discovery of module collections
8
+ - Updated dependencies
9
+ - @veloxts/core@0.7.9
10
+ - @veloxts/validation@0.7.9
11
+
3
12
  ## 0.7.8
4
13
 
5
14
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -51,8 +51,8 @@ export type { RouterResult } from './router-utils.js';
51
51
  export { createRouter, toRouter } from './router-utils.js';
52
52
  export type { NamingWarning, NamingWarningType, WarningConfig, WarningOption } from './warnings.js';
53
53
  export { analyzeNamingConvention, isDevelopment, normalizeWarningOption } from './warnings.js';
54
- export type { ExtractRoutesType, GenerateRestRoutesOptions, RestAdapterOptions, RestMapping, RestRoute, RouteMap, } from './rest/index.js';
55
- export { buildMultiLevelNestedPath, buildNestedRestPath, buildRestPath, calculateNestingDepth, extractRoutes, followsNamingConvention, generateRestRoutes, getRouteSummary, inferResourceName, parseNamingConvention, registerRestRoutes, rest, } from './rest/index.js';
54
+ export type { ExtractRoutesType, GenerateRestRoutesOptions, RegisteredCollection, RestAdapterOptions, RestMapping, RestRoute, RouteMap, } from './rest/index.js';
55
+ export { buildMultiLevelNestedPath, buildNestedRestPath, buildRestPath, calculateNestingDepth, clearCollectionRegistry, extractRoutes, followsNamingConvention, generateRestRoutes, getRegisteredCollections, getRouteSummary, inferResourceName, parseNamingConvention, registerRestRoutes, rest, } from './rest/index.js';
56
56
  export type { AnyRouter, CollectionsToRouterRecord, ExtractNamespace, ExtractProcedures, InferRouterFromCollections, MapProcedureRecordToTRPC, MapProcedureToTRPC, TRPCInstance, TRPCPluginOptions, TRPCRouter, } from './trpc/index.js';
57
57
  export { appRouter, buildTRPCRouter, createTRPCContextFactory, registerTRPCPlugin, trpc, veloxErrorToTRPCError, } from './trpc/index.js';
58
58
  export type { RpcOptions, RpcResult } from './rpc.js';
@@ -82,7 +82,7 @@ export { serve } from './expose.js';
82
82
  * ```
83
83
  */
84
84
  export type { BuildParametersOptions, BuildParametersResult, GuardMappingOptions, JSONSchema, OpenAPIComponents, OpenAPIContact, OpenAPIEncoding, OpenAPIExample, OpenAPIExternalDocs, OpenAPIGeneratorOptions, OpenAPIHeader, OpenAPIHttpMethod, OpenAPIInfo, OpenAPILicense, OpenAPILink, OpenAPIMediaType, OpenAPIOAuthFlow, OpenAPIOAuthFlows, OpenAPIOperation, OpenAPIParameter, OpenAPIPathItem, OpenAPIRequestBody, OpenAPIResponse, OpenAPISecurityRequirement, OpenAPISecurityScheme, OpenAPIServer, OpenAPISpec, OpenAPITag, ParameterIn, QueryParamExtractionOptions, RouteInfo, SchemaConversionOptions, SecuritySchemeType, SwaggerUIConfig, SwaggerUIHtmlOptions, SwaggerUIPluginOptions, } from './openapi/index.js';
85
- export { buildParameters, convertFromOpenAPIPath, convertToOpenAPIPath, createSecurityRequirement, createStringSchema, DEFAULT_GUARD_MAPPINGS, DEFAULT_SECURITY_SCHEMES, DEFAULT_UI_CONFIG, escapeHtml, extractGuardScopes, extractPathParamNames, extractQueryParameters, extractResourceFromPath, extractSchemaProperties, extractUsedSecuritySchemes, filterUsedSecuritySchemes, generateOpenApiSpec, generateSwaggerUIHtml, getOpenApiRouteSummary, getOpenApiSpec, guardsRequireAuth, guardsToSecurity, hasPathParameters, joinPaths, mapGuardToSecurity, mergeSchemas, mergeSecuritySchemes, normalizePath, parsePathParameters, removeSchemaProperties, SWAGGER_UI_CDN, schemaHasProperties, swaggerPlugin, validateOpenApiSpec, zodSchemaToJsonSchema, } from './openapi/index.js';
85
+ export { buildParameters, convertFromOpenAPIPath, convertToOpenAPIPath, createSecurityRequirement, createStringSchema, DEFAULT_GUARD_MAPPINGS, DEFAULT_SECURITY_SCHEMES, DEFAULT_UI_CONFIG, escapeHtml, extractGuardScopes, extractPathParamNames, extractQueryParameters, extractResourceFromPath, extractSchemaProperties, extractUsedSecuritySchemes, filterUsedSecuritySchemes, generateOpenApiSpec, generateOpenApiSpecFromRegistry, generateSwaggerUIHtml, getOpenApiRouteSummary, getOpenApiSpec, guardsRequireAuth, guardsToSecurity, hasPathParameters, joinPaths, mapGuardToSecurity, mergeSchemas, mergeSecuritySchemes, normalizePath, parsePathParameters, removeSchemaProperties, SWAGGER_UI_CDN, schemaHasProperties, swaggerPlugin, validateOpenApiSpec, zodSchemaToJsonSchema, } from './openapi/index.js';
86
86
  export type { AccessLevel, AccessLevelConfig, ADMIN, AdminOutput, AdminTaggedContext, ANONYMOUS, AnonymousOutput, AnonymousTaggedContext, AnyResourceOutput, AUTHENTICATED, AuthenticatedOutput, AuthenticatedTaggedContext, BuilderField, ContextTag, CustomResourceSchemaWithViews, CustomSchemaBuilder, ExtractTag, FilterFieldsByLevel, HasTag, IfAdmin, IfAuthenticated, InferResourceData, InferResourceOutput, IsVisibleToTag, LevelToTag, OutputForLevel, OutputForTag, PUBLIC, PublicOutput, PublicTaggedContext, RelationField, ResourceField, ResourceSchema, ResourceSchemaWithViews, RuntimeField, TaggedContext, TagToLevel, VisibilityLevel, WithTag, } from './resource/index.js';
87
87
  /**
88
88
  * Resource API for context-dependent output types using phantom types.
package/dist/index.js CHANGED
@@ -58,7 +58,7 @@ defineProcedures, executeProcedure, isCompiledProcedure, isProcedureCollection,
58
58
  export { createProcedure, typedProcedure } from './procedure/factory.js';
59
59
  export { createRouter, toRouter } from './router-utils.js';
60
60
  export { analyzeNamingConvention, isDevelopment, normalizeWarningOption } from './warnings.js';
61
- export { buildMultiLevelNestedPath, buildNestedRestPath, buildRestPath, calculateNestingDepth, extractRoutes, followsNamingConvention, generateRestRoutes, getRouteSummary, inferResourceName, parseNamingConvention, registerRestRoutes, rest, } from './rest/index.js';
61
+ export { buildMultiLevelNestedPath, buildNestedRestPath, buildRestPath, calculateNestingDepth, clearCollectionRegistry, extractRoutes, followsNamingConvention, generateRestRoutes, getRegisteredCollections, getRouteSummary, inferResourceName, parseNamingConvention, registerRestRoutes, rest, } from './rest/index.js';
62
62
  export {
63
63
  // tRPC utilities
64
64
  appRouter, buildTRPCRouter, createTRPCContextFactory, registerTRPCPlugin, trpc, veloxErrorToTRPCError, } from './trpc/index.js';
@@ -73,7 +73,7 @@ createSecurityRequirement,
73
73
  // Schema converter
74
74
  createStringSchema, DEFAULT_GUARD_MAPPINGS, DEFAULT_SECURITY_SCHEMES, DEFAULT_UI_CONFIG, escapeHtml, extractGuardScopes, extractPathParamNames, extractQueryParameters, extractResourceFromPath, extractSchemaProperties, extractUsedSecuritySchemes, filterUsedSecuritySchemes,
75
75
  // Generator
76
- generateOpenApiSpec,
76
+ generateOpenApiSpec, generateOpenApiSpecFromRegistry,
77
77
  // HTML Generator
78
78
  generateSwaggerUIHtml, getOpenApiRouteSummary, getOpenApiSpec, guardsRequireAuth, guardsToSecurity, hasPathParameters, joinPaths, mapGuardToSecurity, mergeSchemas, mergeSecuritySchemes, normalizePath, parsePathParameters, removeSchemaProperties, SWAGGER_UI_CDN, schemaHasProperties,
79
79
  // Plugin
@@ -5,11 +5,15 @@
5
5
  *
6
6
  * @module @veloxts/router/openapi/generator
7
7
  */
8
+ import type { RegisteredCollection } from '../rest/registry.js';
8
9
  import type { ProcedureCollection } from '../types.js';
9
10
  import type { OpenAPIGeneratorOptions, OpenAPISpec } from './types.js';
10
11
  /**
11
12
  * Generates an OpenAPI 3.0.3 specification from procedure collections
12
13
  *
14
+ * All collections share the same prefix from `options.prefix` (default '/api').
15
+ * For collections with different prefixes, use `generateOpenApiSpecFromRegistry()`.
16
+ *
13
17
  * @param collections - Array of procedure collections to document
14
18
  * @param options - Generator options
15
19
  * @returns Complete OpenAPI specification
@@ -30,6 +34,27 @@ import type { OpenAPIGeneratorOptions, OpenAPISpec } from './types.js';
30
34
  * ```
31
35
  */
32
36
  export declare function generateOpenApiSpec(collections: ProcedureCollection[], options: OpenAPIGeneratorOptions): OpenAPISpec;
37
+ /**
38
+ * Generates an OpenAPI 3.0.3 specification from registered collections
39
+ *
40
+ * Each entry carries its own prefix, allowing collections registered under
41
+ * different Fastify prefixes (e.g., `/api` and `/loterie`) to produce
42
+ * correct paths in a single spec.
43
+ *
44
+ * @param entries - Registered collections with per-entry prefixes
45
+ * @param options - Generator options (prefix field is ignored — per-entry prefix is used)
46
+ * @returns Complete OpenAPI specification
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * import { generateOpenApiSpecFromRegistry, getRegisteredCollections } from '@veloxts/router';
51
+ *
52
+ * const spec = generateOpenApiSpecFromRegistry(getRegisteredCollections(), {
53
+ * info: { title: 'My API', version: '1.0.0' },
54
+ * });
55
+ * ```
56
+ */
57
+ export declare function generateOpenApiSpecFromRegistry(entries: readonly RegisteredCollection[], options: OpenAPIGeneratorOptions): OpenAPISpec;
33
58
  /**
34
59
  * Gets route summary information for debugging/logging
35
60
  *
@@ -15,6 +15,9 @@ import { extractUsedSecuritySchemes, filterUsedSecuritySchemes, guardsToSecurity
15
15
  /**
16
16
  * Generates an OpenAPI 3.0.3 specification from procedure collections
17
17
  *
18
+ * All collections share the same prefix from `options.prefix` (default '/api').
19
+ * For collections with different prefixes, use `generateOpenApiSpecFromRegistry()`.
20
+ *
18
21
  * @param collections - Array of procedure collections to document
19
22
  * @param options - Generator options
20
23
  * @returns Complete OpenAPI specification
@@ -36,20 +39,53 @@ import { extractUsedSecuritySchemes, filterUsedSecuritySchemes, guardsToSecurity
36
39
  */
37
40
  export function generateOpenApiSpec(collections, options) {
38
41
  const prefix = options.prefix ?? '/api';
42
+ // Convert to RegisteredCollection entries with the shared prefix
43
+ const entries = collections.map((collection) => ({
44
+ collection,
45
+ prefix,
46
+ }));
47
+ return generateOpenApiSpecFromRegistry(entries, options);
48
+ }
49
+ /**
50
+ * Generates an OpenAPI 3.0.3 specification from registered collections
51
+ *
52
+ * Each entry carries its own prefix, allowing collections registered under
53
+ * different Fastify prefixes (e.g., `/api` and `/loterie`) to produce
54
+ * correct paths in a single spec.
55
+ *
56
+ * @param entries - Registered collections with per-entry prefixes
57
+ * @param options - Generator options (prefix field is ignored — per-entry prefix is used)
58
+ * @returns Complete OpenAPI specification
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * import { generateOpenApiSpecFromRegistry, getRegisteredCollections } from '@veloxts/router';
63
+ *
64
+ * const spec = generateOpenApiSpecFromRegistry(getRegisteredCollections(), {
65
+ * info: { title: 'My API', version: '1.0.0' },
66
+ * });
67
+ * ```
68
+ */
69
+ export function generateOpenApiSpecFromRegistry(entries, options) {
39
70
  const paths = {};
40
71
  const tags = [];
41
72
  const allGuards = [];
42
- // Process each collection
43
- for (const collection of collections) {
73
+ const seenTagNames = new Set();
74
+ // Process each registered entry
75
+ for (const entry of entries) {
76
+ const { collection, prefix } = entry;
44
77
  const routes = generateRestRoutes(collection);
45
- // Add tag for this namespace
46
- tags.push({
47
- name: collection.namespace,
48
- description: options.tagDescriptions?.[collection.namespace],
49
- });
78
+ // Add tag for this namespace (deduplicate across entries)
79
+ if (!seenTagNames.has(collection.namespace)) {
80
+ seenTagNames.add(collection.namespace);
81
+ tags.push({
82
+ name: collection.namespace,
83
+ description: options.tagDescriptions?.[collection.namespace],
84
+ });
85
+ }
50
86
  // Process each route
51
87
  for (const route of routes) {
52
- // Build full path with prefix
88
+ // Build full path with this entry's prefix
53
89
  const fullPath = joinPaths(prefix, route.path);
54
90
  const openApiPath = convertToOpenAPIPath(fullPath);
55
91
  // Initialize path item if not exists
@@ -28,7 +28,7 @@
28
28
  * });
29
29
  * ```
30
30
  */
31
- export { generateOpenApiSpec, getOpenApiRouteSummary, validateOpenApiSpec, } from './generator.js';
31
+ export { generateOpenApiSpec, generateOpenApiSpecFromRegistry, getOpenApiRouteSummary, validateOpenApiSpec, } from './generator.js';
32
32
  export { getOpenApiSpec, swaggerPlugin, } from './plugin.js';
33
33
  export { DEFAULT_UI_CONFIG, escapeHtml, generateSwaggerUIHtml, SWAGGER_UI_CDN, type SwaggerUIHtmlOptions, } from './html-generator.js';
34
34
  export { createStringSchema, extractSchemaProperties, mergeSchemas, removeSchemaProperties, type SchemaConversionOptions, schemaHasProperties, zodSchemaToJsonSchema, } from './schema-converter.js';
@@ -31,7 +31,7 @@
31
31
  // ============================================================================
32
32
  // Generator
33
33
  // ============================================================================
34
- export { generateOpenApiSpec, getOpenApiRouteSummary, validateOpenApiSpec, } from './generator.js';
34
+ export { generateOpenApiSpec, generateOpenApiSpecFromRegistry, getOpenApiRouteSummary, validateOpenApiSpec, } from './generator.js';
35
35
  // ============================================================================
36
36
  // Plugin
37
37
  // ============================================================================
@@ -12,22 +12,27 @@ import type { OpenAPISpec, SwaggerUIPluginOptions } from './types.js';
12
12
  *
13
13
  * Registers routes for serving Swagger UI and the OpenAPI specification.
14
14
  *
15
+ * When `collections` is omitted, the plugin auto-discovers all collections
16
+ * previously registered via `rest()`, using each collection's effective prefix.
17
+ *
15
18
  * @example
16
19
  * ```typescript
17
20
  * import { swaggerPlugin } from '@veloxts/router';
18
21
  *
22
+ * // Explicit collections (backward compatible)
19
23
  * app.register(swaggerPlugin, {
20
24
  * routePrefix: '/docs',
21
25
  * collections: [userProcedures, postProcedures],
22
26
  * openapi: {
23
- * info: {
24
- * title: 'My API',
25
- * version: '1.0.0',
26
- * description: 'A VeloxTS-powered API',
27
- * },
27
+ * info: { title: 'My API', version: '1.0.0' },
28
28
  * servers: [{ url: 'http://localhost:3030' }],
29
29
  * },
30
30
  * });
31
+ *
32
+ * // Auto-discovery — no collections needed
33
+ * app.register(swaggerPlugin, {
34
+ * openapi: { info: { title: 'My API', version: '1.0.0' } },
35
+ * });
31
36
  * ```
32
37
  */
33
38
  export declare const swaggerPlugin: FastifyPluginAsync<SwaggerUIPluginOptions>;
@@ -35,6 +40,7 @@ export declare const swaggerPlugin: FastifyPluginAsync<SwaggerUIPluginOptions>;
35
40
  * Gets the generated OpenAPI specification without registering routes
36
41
  *
37
42
  * Useful for testing or exporting the spec programmatically.
43
+ * Supports auto-discovery when `collections` is omitted.
38
44
  *
39
45
  * @param options - Plugin options
40
46
  * @returns Generated OpenAPI specification
@@ -5,9 +5,27 @@
5
5
  *
6
6
  * @module @veloxts/router/openapi/plugin
7
7
  */
8
- import { generateOpenApiSpec } from './generator.js';
8
+ import { getRegisteredCollections } from '../rest/registry.js';
9
+ import { generateOpenApiSpec, generateOpenApiSpecFromRegistry } from './generator.js';
9
10
  import { generateSwaggerUIHtml } from './html-generator.js';
10
11
  // ============================================================================
12
+ // Internal Helpers
13
+ // ============================================================================
14
+ /**
15
+ * Build an OpenAPI spec from plugin options.
16
+ *
17
+ * - Explicit `collections` → use `generateOpenApiSpec` (single global prefix)
18
+ * - No collections → auto-discover from the registry (per-entry prefix)
19
+ */
20
+ function buildSpec(options) {
21
+ const { collections, openapi } = options;
22
+ if (collections && collections.length > 0) {
23
+ return generateOpenApiSpec(collections, openapi);
24
+ }
25
+ const registered = getRegisteredCollections();
26
+ return generateOpenApiSpecFromRegistry(registered, openapi);
27
+ }
28
+ // ============================================================================
11
29
  // Fastify Plugin
12
30
  // ============================================================================
13
31
  /**
@@ -15,30 +33,35 @@ import { generateSwaggerUIHtml } from './html-generator.js';
15
33
  *
16
34
  * Registers routes for serving Swagger UI and the OpenAPI specification.
17
35
  *
36
+ * When `collections` is omitted, the plugin auto-discovers all collections
37
+ * previously registered via `rest()`, using each collection's effective prefix.
38
+ *
18
39
  * @example
19
40
  * ```typescript
20
41
  * import { swaggerPlugin } from '@veloxts/router';
21
42
  *
43
+ * // Explicit collections (backward compatible)
22
44
  * app.register(swaggerPlugin, {
23
45
  * routePrefix: '/docs',
24
46
  * collections: [userProcedures, postProcedures],
25
47
  * openapi: {
26
- * info: {
27
- * title: 'My API',
28
- * version: '1.0.0',
29
- * description: 'A VeloxTS-powered API',
30
- * },
48
+ * info: { title: 'My API', version: '1.0.0' },
31
49
  * servers: [{ url: 'http://localhost:3030' }],
32
50
  * },
33
51
  * });
52
+ *
53
+ * // Auto-discovery — no collections needed
54
+ * app.register(swaggerPlugin, {
55
+ * openapi: { info: { title: 'My API', version: '1.0.0' } },
56
+ * });
34
57
  * ```
35
58
  */
36
59
  export const swaggerPlugin = async (fastify, options) => {
37
- const { routePrefix = '/docs', specRoute = `${routePrefix}/openapi.json`, uiConfig = {}, openapi, collections, title = 'API Documentation', favicon, } = options;
60
+ const { routePrefix = '/docs', specRoute = `${routePrefix}/openapi.json`, uiConfig = {}, title = 'API Documentation', favicon, } = options;
38
61
  // Generate the OpenAPI specification
39
62
  let spec;
40
63
  try {
41
- spec = generateOpenApiSpec(collections, openapi);
64
+ spec = buildSpec(options);
42
65
  }
43
66
  catch (error) {
44
67
  fastify.log.error(error, '[VeloxTS] Failed to generate OpenAPI specification');
@@ -73,6 +96,7 @@ export const swaggerPlugin = async (fastify, options) => {
73
96
  * Gets the generated OpenAPI specification without registering routes
74
97
  *
75
98
  * Useful for testing or exporting the spec programmatically.
99
+ * Supports auto-discovery when `collections` is omitted.
76
100
  *
77
101
  * @param options - Plugin options
78
102
  * @returns Generated OpenAPI specification
@@ -93,5 +117,5 @@ export const swaggerPlugin = async (fastify, options) => {
93
117
  * ```
94
118
  */
95
119
  export function getOpenApiSpec(options) {
96
- return generateOpenApiSpec(options.collections, options.openapi);
120
+ return buildSpec(options);
97
121
  }
@@ -404,9 +404,12 @@ export interface SwaggerUIPluginOptions {
404
404
  */
405
405
  openapi: OpenAPIGeneratorOptions;
406
406
  /**
407
- * Procedure collections to document
407
+ * Procedure collections to document.
408
+ *
409
+ * When omitted, the plugin auto-discovers collections registered via `rest()`
410
+ * along with their effective prefixes.
408
411
  */
409
- collections: ProcedureCollection[];
412
+ collections?: ProcedureCollection[];
410
413
  /**
411
414
  * Custom page title
412
415
  * @default 'API Documentation'
@@ -11,6 +11,7 @@ import { ConfigurationError, createLogger } from '@veloxts/core';
11
11
  const log = createLogger('router');
12
12
  import { executeProcedure } from '../procedure/builder.js';
13
13
  import { buildMultiLevelNestedPath, buildNestedRestPath, buildRestPath, calculateNestingDepth, parseNamingConvention, } from './naming.js';
14
+ import { registerCollections } from './registry.js';
14
15
  /** Default nesting depth threshold for warnings */
15
16
  const NESTING_DEPTH_WARNING_THRESHOLD = 3;
16
17
  /**
@@ -321,6 +322,11 @@ export function registerRestRoutes(server, collections, options = {}) {
321
322
  server.route({ method: route.method, url: fullPath, handler });
322
323
  }
323
324
  }
325
+ // Register collections in the shared registry for swagger auto-discovery.
326
+ // Plugin mode: server.prefix gives the accumulated Fastify prefix (e.g., '/loterie')
327
+ // Global mode: use the prefix option (e.g., '/api')
328
+ const effectivePrefix = _prefixHandledByFastify ? server.prefix : prefix;
329
+ registerCollections(collections, effectivePrefix);
324
330
  }
325
331
  /**
326
332
  * Get a summary of routes that would be generated from collections
@@ -7,5 +7,7 @@ export type { GenerateRestRoutesOptions, RestAdapterOptions, RestPlugin, RestRou
7
7
  export { generateRestRoutes, getRouteSummary, registerRestRoutes, rest, } from './adapter.js';
8
8
  export type { RestMapping } from './naming.js';
9
9
  export { buildMultiLevelNestedPath, buildNestedRestPath, buildRestPath, calculateNestingDepth, followsNamingConvention, inferResourceName, parseNamingConvention, } from './naming.js';
10
+ export type { RegisteredCollection } from './registry.js';
11
+ export { clearCollectionRegistry, getRegisteredCollections, registerCollections, } from './registry.js';
10
12
  export type { ExtractRoutesType, RouteEntry, RouteMap } from './routes.js';
11
13
  export { extractRoutes } from './routes.js';
@@ -5,4 +5,5 @@
5
5
  */
6
6
  export { generateRestRoutes, getRouteSummary, registerRestRoutes, rest, } from './adapter.js';
7
7
  export { buildMultiLevelNestedPath, buildNestedRestPath, buildRestPath, calculateNestingDepth, followsNamingConvention, inferResourceName, parseNamingConvention, } from './naming.js';
8
+ export { clearCollectionRegistry, getRegisteredCollections, registerCollections, } from './registry.js';
8
9
  export { extractRoutes } from './routes.js';
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Collection Registry
3
+ *
4
+ * Tracks procedure collections and their effective prefixes as they are
5
+ * registered via `rest()`. Enables auto-discovery by the swagger plugin
6
+ * so users don't have to manually pass collections.
7
+ *
8
+ * @module rest/registry
9
+ */
10
+ import type { ProcedureCollection } from '../types.js';
11
+ /**
12
+ * A procedure collection paired with its effective route prefix
13
+ */
14
+ export interface RegisteredCollection {
15
+ readonly collection: ProcedureCollection;
16
+ readonly prefix: string;
17
+ }
18
+ /**
19
+ * Register one or more procedure collections with their effective prefix
20
+ *
21
+ * Called internally by `registerRestRoutes()` after routes are mounted.
22
+ *
23
+ * @param collections - Procedure collections being registered
24
+ * @param prefix - The effective route prefix (e.g., '/api', '/loterie')
25
+ */
26
+ export declare function registerCollections(collections: readonly ProcedureCollection[], prefix: string): void;
27
+ /**
28
+ * Get all registered collections with their prefixes
29
+ *
30
+ * Used by `swaggerPlugin` for auto-discovery when no explicit
31
+ * `collections` option is provided.
32
+ */
33
+ export declare function getRegisteredCollections(): readonly RegisteredCollection[];
34
+ /**
35
+ * Clear the collection registry
36
+ *
37
+ * Intended for test isolation — call in `beforeEach` / `afterEach`.
38
+ */
39
+ export declare function clearCollectionRegistry(): void;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Collection Registry
3
+ *
4
+ * Tracks procedure collections and their effective prefixes as they are
5
+ * registered via `rest()`. Enables auto-discovery by the swagger plugin
6
+ * so users don't have to manually pass collections.
7
+ *
8
+ * @module rest/registry
9
+ */
10
+ // ============================================================================
11
+ // Module-level Registry
12
+ // ============================================================================
13
+ const registry = [];
14
+ /**
15
+ * Register one or more procedure collections with their effective prefix
16
+ *
17
+ * Called internally by `registerRestRoutes()` after routes are mounted.
18
+ *
19
+ * @param collections - Procedure collections being registered
20
+ * @param prefix - The effective route prefix (e.g., '/api', '/loterie')
21
+ */
22
+ export function registerCollections(collections, prefix) {
23
+ for (const collection of collections) {
24
+ registry.push({ collection, prefix });
25
+ }
26
+ }
27
+ /**
28
+ * Get all registered collections with their prefixes
29
+ *
30
+ * Used by `swaggerPlugin` for auto-discovery when no explicit
31
+ * `collections` option is provided.
32
+ */
33
+ export function getRegisteredCollections() {
34
+ return registry;
35
+ }
36
+ /**
37
+ * Clear the collection registry
38
+ *
39
+ * Intended for test isolation — call in `beforeEach` / `afterEach`.
40
+ */
41
+ export function clearCollectionRegistry() {
42
+ registry.length = 0;
43
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veloxts/router",
3
- "version": "0.7.8",
3
+ "version": "0.7.9",
4
4
  "description": "Procedure definitions with tRPC and REST routing for VeloxTS framework",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -39,8 +39,8 @@
39
39
  "dependencies": {
40
40
  "@trpc/server": "11.10.0",
41
41
  "fastify": "5.7.4",
42
- "@veloxts/core": "0.7.8",
43
- "@veloxts/validation": "0.7.8"
42
+ "@veloxts/core": "0.7.9",
43
+ "@veloxts/validation": "0.7.9"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@vitest/coverage-v8": "4.0.18",