@warlock.js/core 4.5.0 → 4.6.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.
- package/CHANGELOG.md +27 -0
- package/esm/ai/src/agent/agent.mjs +126 -7
- package/esm/ai/src/agent/agent.mjs.map +1 -1
- package/esm/ai/src/agent/signature.mjs +57 -0
- package/esm/ai/src/agent/signature.mjs.map +1 -0
- package/esm/ai/src/agent/snapshot.mjs +101 -0
- package/esm/ai/src/agent/snapshot.mjs.map +1 -0
- package/esm/ai/src/ai.mjs +37 -1
- package/esm/ai/src/ai.mjs.map +1 -1
- package/esm/ai/src/errors/agent-drift-error.mjs +31 -0
- package/esm/ai/src/errors/agent-drift-error.mjs.map +1 -0
- package/esm/ai/src/errors/index.mjs +2 -0
- package/esm/ai/src/errors/planner-drift-error.mjs +33 -0
- package/esm/ai/src/errors/planner-drift-error.mjs.map +1 -0
- package/esm/ai/src/image/image-cost.mjs +55 -0
- package/esm/ai/src/image/image-cost.mjs.map +1 -0
- package/esm/ai/src/image/image.mjs +112 -0
- package/esm/ai/src/image/image.mjs.map +1 -0
- package/esm/ai/src/image/index.mjs +4 -0
- package/esm/ai/src/index.mjs +20 -0
- package/esm/ai/src/planner/planner-run.mjs +161 -6
- package/esm/ai/src/planner/planner-run.mjs.map +1 -1
- package/esm/ai/src/planner/planner.mjs +25 -1
- package/esm/ai/src/planner/planner.mjs.map +1 -1
- package/esm/ai/src/planner/snapshot.mjs +95 -0
- package/esm/ai/src/planner/snapshot.mjs.map +1 -0
- package/esm/ai/src/rag/hybrid/bm25.mjs +51 -0
- package/esm/ai/src/rag/hybrid/bm25.mjs.map +1 -0
- package/esm/ai/src/rag/hybrid/hybrid-rank.mjs +29 -0
- package/esm/ai/src/rag/hybrid/hybrid-rank.mjs.map +1 -0
- package/esm/ai/src/rag/hybrid/rrf.mjs +30 -0
- package/esm/ai/src/rag/hybrid/rrf.mjs.map +1 -0
- package/esm/ai/src/rag/index.mjs +11 -0
- package/esm/ai/src/rag/loaders/errors.mjs +25 -0
- package/esm/ai/src/rag/loaders/errors.mjs.map +1 -0
- package/esm/ai/src/rag/loaders/index.mjs +7 -0
- package/esm/ai/src/rag/loaders/load-html.mjs +138 -0
- package/esm/ai/src/rag/loaders/load-html.mjs.map +1 -0
- package/esm/ai/src/rag/loaders/load-pdf.mjs +150 -0
- package/esm/ai/src/rag/loaders/load-pdf.mjs.map +1 -0
- package/esm/ai/src/rag/loaders/load-text.mjs +60 -0
- package/esm/ai/src/rag/loaders/load-text.mjs.map +1 -0
- package/esm/ai/src/rag/loaders/load-web.mjs +89 -0
- package/esm/ai/src/rag/loaders/load-web.mjs.map +1 -0
- package/esm/ai/src/rag/store/pg-vector-store.mjs +328 -0
- package/esm/ai/src/rag/store/pg-vector-store.mjs.map +1 -0
- package/esm/ai/src/rag/transforms/multi-query.mjs +41 -0
- package/esm/ai/src/rag/transforms/multi-query.mjs.map +1 -0
- package/esm/ai/src/speech/index.mjs +3 -0
- package/esm/ai/src/speech/speech.mjs +122 -0
- package/esm/ai/src/speech/speech.mjs.map +1 -0
- package/esm/ai/src/supervisor/entries.mjs +2 -2
- package/esm/ai/src/supervisor/entries.mjs.map +1 -1
- package/esm/ai/src/transcribe/audio-input.mjs +84 -0
- package/esm/ai/src/transcribe/audio-input.mjs.map +1 -0
- package/esm/ai/src/transcribe/index.mjs +4 -0
- package/esm/ai/src/transcribe/transcribe.mjs +127 -0
- package/esm/ai/src/transcribe/transcribe.mjs.map +1 -0
- package/esm/ai-openai/src/image.mjs +5 -0
- package/esm/ai-openai/src/index.mjs +3 -0
- package/esm/ai-openai/src/sdk.mjs +3 -0
- package/esm/ai-openai/src/speech.mjs +5 -0
- package/esm/ai-openai/src/transcription.mjs +6 -0
- package/esm/ai-openai/src/utils/index.mjs +1 -0
- package/esm/ai-openai/src/utils/to-openai-messages.mjs +3 -0
- package/esm/cli/commands/doctor/checks/config.check.mjs +42 -0
- package/esm/cli/commands/doctor/checks/config.check.mjs.map +1 -0
- package/esm/cli/commands/doctor/checks/connectors.check.mjs +28 -0
- package/esm/cli/commands/doctor/checks/connectors.check.mjs.map +1 -0
- package/esm/cli/commands/doctor/checks/health.check.mjs +35 -0
- package/esm/cli/commands/doctor/checks/health.check.mjs.map +1 -0
- package/esm/cli/commands/doctor/checks/index.mjs +25 -0
- package/esm/cli/commands/doctor/checks/index.mjs.map +1 -0
- package/esm/cli/commands/doctor/checks/optional-peers.check.mjs +90 -0
- package/esm/cli/commands/doctor/checks/optional-peers.check.mjs.map +1 -0
- package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs +69 -0
- package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs.map +1 -0
- package/esm/cli/commands/doctor/checks/routes.check.mjs +30 -0
- package/esm/cli/commands/doctor/checks/routes.check.mjs.map +1 -0
- package/esm/cli/commands/doctor/doctor-command.action.mjs +28 -0
- package/esm/cli/commands/doctor/doctor-command.action.mjs.map +1 -0
- package/esm/cli/commands/doctor/format-report.mjs +44 -0
- package/esm/cli/commands/doctor/format-report.mjs.map +1 -0
- package/esm/cli/commands/doctor/run-checks.mjs +50 -0
- package/esm/cli/commands/doctor/run-checks.mjs.map +1 -0
- package/esm/cli/commands/doctor.command.mjs +29 -0
- package/esm/cli/commands/doctor.command.mjs.map +1 -0
- package/esm/cli/commands/generate/templates/stubs.mjs +6 -8
- package/esm/cli/commands/generate/templates/stubs.mjs.map +1 -1
- package/esm/cli/commands/routes/format-routes-table.mjs +129 -0
- package/esm/cli/commands/routes/format-routes-table.mjs.map +1 -0
- package/esm/cli/commands/routes/route-row.mjs +92 -0
- package/esm/cli/commands/routes/route-row.mjs.map +1 -0
- package/esm/cli/commands/routes/routes-command.action.mjs +43 -0
- package/esm/cli/commands/routes/routes-command.action.mjs.map +1 -0
- package/esm/cli/commands/routes.command.mjs +51 -0
- package/esm/cli/commands/routes.command.mjs.map +1 -0
- package/esm/cli/commands/seed.command.mjs +5 -0
- package/esm/cli/commands/seed.command.mjs.map +1 -1
- package/esm/cli/framework-cli-commands.mjs +4 -0
- package/esm/cli/framework-cli-commands.mjs.map +1 -1
- package/esm/config/config-getter.mjs +5 -5
- package/esm/config/config-getter.mjs.map +1 -1
- package/esm/config/config-loader.mjs +2 -2
- package/esm/config/config-loader.mjs.map +1 -1
- package/esm/connectors/access-connector.mjs +2 -2
- package/esm/connectors/access-connector.mjs.map +1 -1
- package/esm/connectors/ai-connector.mjs +2 -2
- package/esm/connectors/ai-connector.mjs.map +1 -1
- package/esm/connectors/cache-connector.mjs +2 -2
- package/esm/connectors/cache-connector.mjs.map +1 -1
- package/esm/connectors/database-connector.mjs +2 -2
- package/esm/connectors/database-connector.mjs.map +1 -1
- package/esm/connectors/herald-connector.mjs +2 -2
- package/esm/connectors/herald-connector.mjs.map +1 -1
- package/esm/connectors/http-connector.d.mts.map +1 -1
- package/esm/connectors/http-connector.mjs +9 -7
- package/esm/connectors/http-connector.mjs.map +1 -1
- package/esm/connectors/logger-connector.mjs +2 -2
- package/esm/connectors/logger-connector.mjs.map +1 -1
- package/esm/connectors/mail-connector.mjs +2 -2
- package/esm/connectors/mail-connector.mjs.map +1 -1
- package/esm/connectors/notifications-connector.mjs +2 -2
- package/esm/connectors/notifications-connector.mjs.map +1 -1
- package/esm/connectors/socket-connector.mjs +3 -3
- package/esm/connectors/socket-connector.mjs.map +1 -1
- package/esm/database/index.d.mts +2 -1
- package/esm/database/index.mjs +1 -0
- package/esm/database/seed-command-action.mjs +44 -4
- package/esm/database/seed-command-action.mjs.map +1 -1
- package/esm/database/seeds/seed-records-table-migration.mjs +36 -0
- package/esm/database/seeds/seed-records-table-migration.mjs.map +1 -0
- package/esm/database/seeds/seeder.d.mts +22 -5
- package/esm/database/seeds/seeder.d.mts.map +1 -1
- package/esm/database/seeds/seeder.errors.d.mts +22 -0
- package/esm/database/seeds/seeder.errors.d.mts.map +1 -0
- package/esm/database/seeds/seeder.errors.mjs +29 -0
- package/esm/database/seeds/seeder.errors.mjs.map +1 -0
- package/esm/database/seeds/seeder.mjs.map +1 -1
- package/esm/database/seeds/seeders.manager.mjs +90 -11
- package/esm/database/seeds/seeders.manager.mjs.map +1 -1
- package/esm/database/seeds/types.d.mts +117 -1
- package/esm/database/seeds/types.d.mts.map +1 -1
- package/esm/database/seeds/utils.mjs +6 -1
- package/esm/database/seeds/utils.mjs.map +1 -1
- package/esm/dev-server/module-loader.d.mts +12 -0
- package/esm/dev-server/module-loader.d.mts.map +1 -1
- package/esm/dev-server/module-loader.mjs +30 -2
- package/esm/dev-server/module-loader.mjs.map +1 -1
- package/esm/http/config.mjs +2 -2
- package/esm/http/config.mjs.map +1 -1
- package/esm/http/createHttpApplication.mjs +2 -2
- package/esm/http/createHttpApplication.mjs.map +1 -1
- package/esm/http/health.d.mts +14 -0
- package/esm/http/health.d.mts.map +1 -1
- package/esm/http/health.mjs +16 -0
- package/esm/http/health.mjs.map +1 -1
- package/esm/http/middleware/idempotency.middleware.mjs +5 -5
- package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
- package/esm/http/middleware/inject-request-context.mjs +2 -2
- package/esm/http/middleware/inject-request-context.mjs.map +1 -1
- package/esm/http/middleware/maintenance.middleware.mjs +4 -4
- package/esm/http/middleware/maintenance.middleware.mjs.map +1 -1
- package/esm/http/plugins.mjs +9 -9
- package/esm/http/plugins.mjs.map +1 -1
- package/esm/http/response.mjs +5 -5
- package/esm/http/response.mjs.map +1 -1
- package/esm/http/server.mjs +4 -4
- package/esm/http/server.mjs.map +1 -1
- package/esm/index.d.mts +4 -3
- package/esm/index.mjs +2 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts +28 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.mjs +39 -0
- package/esm/repositories/adapters/cascade/cascade-query-builder.mjs.map +1 -1
- package/esm/repositories/contracts/index.d.mts +1 -1
- package/esm/repositories/contracts/query-builder.contract.d.mts +87 -1
- package/esm/repositories/contracts/query-builder.contract.d.mts.map +1 -1
- package/esm/repositories/index.d.mts +1 -1
- package/esm/repositories/repository.manager.d.mts +99 -1
- package/esm/repositories/repository.manager.d.mts.map +1 -1
- package/esm/repositories/repository.manager.mjs +128 -0
- package/esm/repositories/repository.manager.mjs.map +1 -1
- package/esm/router/router.d.mts +9 -0
- package/esm/router/router.d.mts.map +1 -1
- package/esm/router/router.mjs +21 -1
- package/esm/router/router.mjs.map +1 -1
- package/esm/utils/paths.mjs +2 -2
- package/esm/utils/paths.mjs.map +1 -1
- package/esm/validation/validateAll.mjs +2 -2
- package/esm/validation/validateAll.mjs.map +1 -1
- package/llms-full.txt +427 -45
- package/llms.txt +4 -2
- package/package.json +9 -9
- package/skills/README.md +65 -0
- package/skills/health-checks/SKILL.md +13 -0
- package/skills/use-repository/SKILL.md +38 -1
- package/skills/warlock-doctor/SKILL.md +135 -0
- package/skills/warlock-routes/SKILL.md +91 -0
- package/skills/write-seeder/SKILL.md +143 -45
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.mjs","names":[],"sources":["../../../../../../../@warlock.js/core/src/router/router.ts"],"sourcesContent":["import proxy, { type FastifyHttpProxyOptions } from \"@fastify/http-proxy\";\nimport fastifyStatic, { type FastifyStaticOptions } from \"@fastify/static\";\nimport concatRoute from \"@mongez/concat-route\";\nimport { ltrim, merge, toCamelCase, trim } from \"@mongez/reinforcements\";\nimport { isEmpty } from \"@mongez/supportive-is\";\nimport { log } from \"@warlock.js/logger\";\nimport type { FastifyReply, FastifyRequest } from \"fastify\";\nimport { container } from \"../container\";\nimport { Request } from \"../http/request\";\nimport { Response } from \"../http/response\";\nimport { type FastifyInstance } from \"../http/server\";\nimport { RouteBuilder } from \"./route-builder\";\nimport { RouteRegistry } from \"./route-registry\";\nimport type {\n GroupedRoutesOptions,\n RequestHandler,\n RequestHandlerType,\n RequestHandlerValidation,\n ResourceMethod,\n Route,\n RouteOptions,\n RouteResource,\n RouterGroupCallback,\n RouterStacks,\n} from \"./types\";\n\nexport class Router {\n /**\n * Routes list\n */\n private routes: Route[] = [];\n\n /**\n * Router Instance\n */\n private static instance: Router;\n\n /**\n * Static paths\n */\n protected staticDirectories: FastifyStaticOptions[] = [];\n\n /**\n * Event listeners\n */\n protected eventListeners: Record<string, ((router: Router, server: FastifyInstance) => void)[]> =\n {};\n\n /**\n * Stacks\n * Stacks will be used for grouping routes to add prefix, name or middleware\n */\n protected stacks: RouterStacks = {\n prefix: [],\n name: [],\n middleware: [],\n };\n\n /**\n * Get router instance\n */\n public static getInstance() {\n if (!Router.instance) {\n Router.instance = new Router();\n }\n\n return Router.instance;\n }\n\n private constructor() {\n //\n }\n\n /**\n * Listen to router before scan\n */\n public beforeScanning(callback: (router: Router, server: FastifyInstance) => void) {\n this.eventListeners.beforeScan = [...(this.eventListeners.beforeScan || []), callback];\n\n return this;\n }\n\n /**\n * Listen to router after scanning\n */\n public afterScanning(callback: (router: Router, server: FastifyInstance) => void) {\n this.eventListeners.afterScanning = [...(this.eventListeners.afterScanning || []), callback];\n\n return this;\n }\n\n /**\n * Redirect path to another path\n */\n public redirect(from: string, to: string, redirectMode: \"temporary\" | \"permanent\" = \"temporary\") {\n return this.get(from, (_request, response) => {\n response.redirect(to, redirectMode === \"temporary\" ? 302 : 301);\n });\n }\n\n /**\n * Server static folder\n */\n public directory(options: FastifyStaticOptions) {\n this.staticDirectories.push(options);\n\n return this;\n }\n\n /**\n * Serve file\n */\n public file(path: string, location: string, cacheTime?: number) {\n return this.get(path, (_request, response) => {\n response.sendFile(location, cacheTime);\n });\n }\n\n /**\n * Serve cached file, it will cache the file to 1 year by default\n */\n public cachedFile(path: string, location: string, cacheTime?: number) {\n return this.get(path, (_request, response) => {\n response.sendCachedFile(location, cacheTime);\n });\n }\n\n /**\n * Serve list of files\n */\n public files(files: Record<string, string>, cacheTime?: number) {\n for (const [path, location] of Object.entries(files)) {\n this.get(path, (_request, response) => {\n response.sendFile(location, cacheTime);\n });\n }\n }\n\n /**\n * Serve list of cached files, it will cache the file to 1 year by default\n */\n public cachedFiles(files: Record<string, string>, cacheTime?: number) {\n for (const [path, location] of Object.entries(files)) {\n this.get(path, (_request, response) => {\n response.sendCachedFile(location, cacheTime);\n });\n }\n }\n\n /**\n * Add proxy route\n */\n public proxy(\n path: string,\n baseUrl: string,\n options?: Omit<FastifyHttpProxyOptions, \"prefix\" | \"upstream\">,\n ): this;\n public proxy(options: FastifyHttpProxyOptions): this;\n public proxy(...args: any[]) {\n this.beforeScanning((_router, server) => {\n if (args.length === 1) {\n server.register(proxy, args[0]);\n } else {\n server.register(proxy, {\n prefix: args[0],\n upstream: args[1],\n ...args[2],\n });\n }\n });\n\n return this;\n }\n\n /**\n * Add route to routes list\n */\n public add(\n method: Route[\"method\"],\n path: string | string[],\n handler: RequestHandlerType,\n options: RouteOptions = {},\n ) {\n if (Array.isArray(path)) {\n path.forEach((p) => this.add(method, p, handler, options));\n return this;\n }\n\n const prefix = this.stacks.prefix.reduce((path, prefix) => {\n return concatRoute(path, prefix);\n }, \"\");\n\n const name = this.stacks.name.reduceRight(\n (name, prefixName) => {\n return trim(prefixName + \".\" + name, \".\");\n },\n options.name || trim(path.replace(/\\//g, \".\"), \".\"),\n );\n\n path = concatRoute(prefix, path);\n\n const middlewarePrecedence = options.middlewarePrecedence || \"after\";\n\n if (middlewarePrecedence === \"before\") {\n options.middleware = [...(options.middleware || []), ...this.stacks.middleware];\n } else {\n options.middleware = [...this.stacks.middleware, ...(options.middleware || [])];\n }\n\n if (Array.isArray(handler)) {\n const [controller, action] = handler;\n\n if (typeof controller[action] !== \"function\") {\n throw new Error(\n `Invalid controller action \"${action}\" for controller \"${controller.constructor.name}\"`,\n );\n }\n\n handler = controller[action].bind(controller) as RequestHandler;\n\n if (!handler.validation) {\n handler.validation = {};\n if (controller[`${action}ValidationSchema`]) {\n handler.validation.schema = controller[`${action}ValidationSchema`]();\n }\n\n if (controller[`${action}Validate`]) {\n handler.validation.validate = controller[`${action}Validate`];\n }\n }\n }\n\n const routeData: Route = {\n method,\n path,\n handler,\n ...options,\n name,\n rateLimit: options.rateLimit,\n $prefix: prefix || \"/\",\n // it must be a new array to avoid modifying the original array\n $prefixStack: [...this.stacks.prefix],\n // Inject source file from stacks if set\n sourceFile: this.stacks.sourceFile || \"\",\n };\n\n if (routeData.name) {\n // check if the name exists\n const route = this.routes.find((route) => route.name === routeData.name);\n\n if (route) {\n // check again if the route name exists with the same method\n if (route.method === routeData.method) {\n throw new Error(`Route name \"${routeData.name}\" already exists`);\n } else {\n routeData.name += `.${routeData.method.toLowerCase()}`;\n }\n }\n }\n\n this.routes.push(routeData);\n\n return this;\n }\n\n /**\n * Add a request that accepts all methods\n */\n public any(path: string, handler: RequestHandlerType, options: RouteOptions = {}) {\n return this.add(\"all\" as Route[\"method\"], path, handler, options);\n }\n\n /**\n * Add get request method\n */\n public get(path: string, handler: RequestHandlerType, options: RouteOptions = {}) {\n return this.add(\"GET\", path, handler, options);\n }\n\n /**\n * Add post request method\n */\n public post(path: string | string[], handler: RequestHandlerType, options: RouteOptions = {}) {\n return this.add(\"POST\", path, handler, options);\n }\n\n /**\n * Add put request method\n */\n public put(path: string, handler: RequestHandlerType, options: RouteOptions = {}) {\n return this.add(\"PUT\", path, handler, options);\n }\n\n /**\n * Add delete request method\n */\n public delete(path: string | string[], handler: RequestHandlerType, options: RouteOptions = {}) {\n return this.add(\"DELETE\", path, handler, options);\n }\n\n /**\n * Add patch request method\n */\n public patch(path: string, handler: RequestHandlerType, options: RouteOptions = {}) {\n return this.add(\"PATCH\", path, handler, options);\n }\n\n /**\n * Add head request method\n */\n public head(path: string, handler: RequestHandlerType, options: RouteOptions = {}) {\n return this.add(\"HEAD\", path, handler, options);\n }\n\n /**\n * Add options request method\n */\n public options(path: string, handler: RequestHandlerType, options: RouteOptions = {}) {\n return this.add(\"OPTIONS\", path, handler, options);\n }\n\n /**\n * Get a chainable route builder for the same route path\n */\n public route(path: string, options: RouteOptions = {}) {\n return new RouteBuilder(this, path, options);\n }\n\n /**\n * Add full restful resource routes\n * This method will generate the following routes:\n * 1. GET /path: list all resources\n * 2. GET /path/:id: get a single resource\n * 3. POST /path: create a new resource\n * 4. PUT /path/:id: update a resource\n * 5. DELETE /path/:id: delete a resource\n * 6. PATCH /path/:id: update a resource partially\n */\n public restfulResource(\n path: string,\n resource: RouteResource,\n options: RouteOptions & {\n only?: ResourceMethod[];\n except?: ResourceMethod[];\n replace?: Partial<Record<ResourceMethod, RequestHandler>> & {\n bulkDelete?: RequestHandler;\n };\n } = {},\n ) {\n return this.prefix(path, () => {\n path = \"\";\n // get base resource name\n const baseResourceName = options.name || toCamelCase(ltrim(path, \"/\"));\n\n // clone the resource so we don't mess up with it\n const routeResource = resource;\n\n const isAcceptableResource = (type: ResourceMethod) => {\n return Boolean(\n // check if the route is not excluded\n (!options.except || !options.except.includes(type)) &&\n // check if the only option is set and the route is included\n (!options.only || options.only.includes(type)),\n );\n };\n\n if (routeResource.list && isAcceptableResource(\"list\")) {\n const resourceName = baseResourceName + \".list\";\n this.get(path, options.replace?.list || routeResource.list.bind(routeResource), {\n ...options,\n name: resourceName,\n restful: true,\n });\n }\n\n if (routeResource.get && isAcceptableResource(\"get\")) {\n const resourceName = baseResourceName + \".single\";\n\n this.get(path + \"/:id\", options.replace?.get || routeResource.get.bind(routeResource), {\n ...options,\n name: resourceName,\n restful: true,\n });\n }\n\n if (routeResource.create && isAcceptableResource(\"create\")) {\n const resourceName = baseResourceName + \".create\";\n\n const handler = options.replace?.create || this.manageValidation(routeResource, \"create\");\n\n this.post(path, handler, {\n ...options,\n name: resourceName,\n restful: true,\n });\n }\n\n if (routeResource.update && isAcceptableResource(\"update\")) {\n const resourceName = baseResourceName + \".update\";\n\n const handler = options.replace?.update || this.manageValidation(routeResource, \"update\");\n\n this.put(path + \"/:id\", handler, {\n ...options,\n name: resourceName,\n restful: true,\n });\n }\n\n if (routeResource.patch && isAcceptableResource(\"patch\")) {\n const resourceName = baseResourceName + \".patch\";\n\n const handler = options.replace?.patch || this.manageValidation(routeResource, \"patch\");\n\n this.patch(path + \"/:id\", handler, {\n ...options,\n name: resourceName,\n restful: true,\n });\n }\n\n if (routeResource.delete && isAcceptableResource(\"delete\")) {\n const resourceName = baseResourceName + \".delete\";\n\n this.delete(\n path + \"/:id\",\n options.replace?.delete || routeResource.delete.bind(routeResource),\n {\n ...options,\n name: resourceName,\n restful: true,\n },\n );\n }\n\n if (routeResource.bulkDelete && isAcceptableResource(\"delete\")) {\n const resourceName = baseResourceName + \".bulkDelete\";\n\n this.delete(\n path,\n options.replace?.bulkDelete || routeResource.bulkDelete.bind(routeResource),\n {\n ...options,\n name: resourceName,\n restful: true,\n },\n );\n }\n\n return this;\n });\n }\n\n /**\n * Group routes with options\n */\n public group(options: GroupedRoutesOptions, callback: RouterGroupCallback) {\n const {\n prefix,\n // name must always be defined because\n // if there are multiple groups without name\n // they might generate the same route name\n // thus causing an error\n // in this case we need always to make sure that\n // the name is always defined.\n name = prefix ? trim(prefix.replace(/\\//g, \".\"), \".\") : undefined,\n middleware,\n } = options;\n\n if (prefix) {\n this.stacks.prefix.push(prefix);\n }\n\n if (name) {\n this.stacks.name.push(name);\n }\n\n if (middleware) {\n this.stacks.middleware.push(...middleware);\n }\n\n try {\n callback();\n } finally {\n // Always pop/splice this group's stacks, even if the callback throws,\n // so a throwing group never leaks state onto the process-global singleton.\n if (prefix) {\n this.stacks.prefix.pop();\n }\n\n if (name) {\n this.stacks.name.pop();\n }\n\n if (middleware) {\n this.stacks.middleware.splice(\n this.stacks.middleware.length - middleware.length,\n middleware.length,\n );\n }\n }\n\n return this;\n }\n\n /**\n * Add prefix to all routes in the given callback\n */\n public prefix(prefix: string, callback: () => void) {\n return this.group({ prefix }, callback);\n }\n\n /**\n * Add API version prefix to all routes in the given callback\n * Automatically formats the version as /v{version}\n * @example\n * router.version(\"1\", () => {\n * router.get(\"/users\", getUsersV1); // /v1/users\n * });\n *\n * router.version(\"2\", () => {\n * router.get(\"/users\", getUsersV2); // /v2/users\n * });\n */\n public version(version: string | number, callback: () => void) {\n return this.prefix(`/v${version}`, callback);\n }\n\n /**\n * Wrap route additions with a source file path\n * Used for tracking which routes come from which file (for HMR)\n * @param sourceFile Relative path to the source file (e.g., \"src/app/users/routes.ts\")\n * @param callback Function that adds routes (will have sourceFile injected)\n */\n public async withSourceFile<T = any>(\n sourceFile: string,\n callback: () => T | Promise<T>,\n ): Promise<T | undefined> {\n // Set source file in stacks\n this.stacks.sourceFile = sourceFile;\n\n try {\n // Execute callback (routes added here will have sourceFile injected)\n return await callback();\n } catch (error) {\n console.log(\"Error in withSourceFile\", error);\n } finally {\n // Always clear source file from stacks\n delete this.stacks.sourceFile;\n }\n }\n\n /**\n * Remove all routes that belong to a specific source file\n * Used when reloading routes files via HMR\n * @param sourceFile Relative path to the source file\n */\n public removeRoutesBySourceFile(sourceFile: string): void {\n this.routes = this.routes.filter((route) => route.sourceFile !== sourceFile);\n }\n\n /**\n * Manage validation system for the given resource\n */\n private manageValidation(resource: RouteResource, method: \"create\" | \"update\" | \"patch\") {\n const handler = resource[method]?.bind(resource) as RequestHandler;\n\n const methodValidation = resource?.validation?.[method];\n\n if (method === \"patch\") {\n handler.validation = methodValidation;\n\n if (handler.validation?.validate) {\n handler.validation.validate = handler.validation.validate.bind(resource);\n }\n\n if (resource.validation?.patch) {\n handler.validation = merge(resource.validation.patch, handler.validation);\n }\n\n return handler;\n }\n\n if (!resource.validation || (!methodValidation && !resource.validation.all)) return handler;\n\n if (resource.validation.all) {\n const validationMethods = {\n all: resource?.validation?.all?.validate,\n [method]: methodValidation?.validate,\n };\n\n const validation: RequestHandlerValidation = {};\n\n if (resource.validation.all.schema || methodValidation?.schema) {\n if (!methodValidation?.schema && resource.validation.all.schema) {\n // Case 2: Only all.schema exists - clone it for this method\n validation.schema = resource.validation.all.schema;\n } else if (methodValidation?.schema && resource.validation.all.schema) {\n // Case 3: Both exist - merge them (all is base, method overrides)\n validation.schema = resource.validation.all.schema.merge(methodValidation.schema);\n } else if (methodValidation?.schema && !resource.validation.all.schema) {\n // Case 1: Only method schema exists - use it directly\n validation.schema = methodValidation.schema;\n }\n // Case 4: Neither exists - handled by outer if being false\n }\n\n if (validationMethods.all || validationMethods[method]) {\n validation.validate = async (request: Request, response: Response) => {\n if (validationMethods.all) {\n const output = await validationMethods.all.call(resource, request, response);\n\n if (output) return output;\n }\n\n if (validationMethods[method]) {\n return await validationMethods[method]?.call(resource, request, response);\n }\n\n return;\n };\n }\n\n if (!isEmpty(validation)) {\n handler.validation = validation;\n }\n } else {\n handler.validation = resource.validation[method];\n\n if (handler.validation?.validate) {\n handler.validation.validate = handler.validation.validate.bind(resource);\n }\n }\n\n return handler;\n }\n\n /**\n * Get all routes list\n */\n public list() {\n return this.routes;\n }\n\n /**\n * Register routes to the server\n */\n public scan(server: FastifyInstance) {\n this.eventListeners.beforeScan?.forEach((callback) => callback(this, server));\n\n this.routes.forEach((route) => {\n const requestMethod = route.method.toLowerCase();\n const requestMethodFunction = server[requestMethod].bind(server);\n\n const options = {\n ...route.serverOptions,\n config: {\n ...route.serverOptions?.config,\n ...(route.rateLimit && { rateLimit: route.rateLimit }),\n },\n };\n\n requestMethodFunction(\n route.path,\n options,\n async (baseRequest: FastifyRequest, reply: FastifyReply) => {\n const { output, response } = await this.handleRoute(route)(baseRequest, reply);\n\n return output || response.baseResponse;\n },\n );\n });\n\n for (const directoryOptions of this.staticDirectories) {\n server.register(fastifyStatic, {\n ...directoryOptions,\n decorateReply: false,\n });\n }\n\n this.eventListeners.afterScanning?.forEach((callback) => callback(this, server));\n }\n\n /**\n * Scan routes for the development server\n * Uses wildcard routing with find-my-way for HMR support\n */\n public scanDevServer(server: FastifyInstance) {\n this.eventListeners.beforeScan?.forEach((callback) => callback(this, server));\n\n // Shared handler for wildcard routing\n const wildcardHandler = async (fastifyRequest: FastifyRequest, fastifyReply: FastifyReply) => {\n // Initialize route registry once (will be rebuilt on HMR via rebuildRouteRegistry)\n const routeRegistry = new RouteRegistry();\n\n routeRegistry.register(this.routes);\n // Find matching route using find-my-way\n const match = routeRegistry.find(fastifyRequest.method, fastifyRequest.url);\n\n // No match found - return 404\n if (!match) {\n return fastifyReply.code(404).send({\n error: \"Route not found\",\n path: fastifyRequest.url,\n method: fastifyRequest.method,\n });\n }\n\n // Inject extracted params into the request\n fastifyRequest.params = match.params;\n\n try {\n // Call the matched route handler\n const { output, response } = await this.handleRoute(match.route)(\n fastifyRequest,\n fastifyReply,\n );\n\n return output || response.baseResponse;\n } catch (error) {\n console.log(error);\n throw error;\n }\n };\n\n // Register wildcard route for all methods EXCEPT OPTIONS (to avoid conflict with CORS)\n // OPTIONS is handled by @fastify/cors plugin for preflight requests\n const methods = [\"GET\", \"POST\", \"PUT\", \"DELETE\", \"PATCH\"] as const;\n for (const method of methods) {\n server.route({\n method,\n url: \"*\",\n handler: wildcardHandler,\n });\n }\n\n // Register static directories\n for (const directoryOptions of this.staticDirectories) {\n server.register(fastifyStatic, {\n ...directoryOptions,\n decorateReply: false,\n });\n }\n\n this.eventListeners.afterScanning?.forEach((callback) => callback(this, server));\n }\n\n /**\n * Get the route path for the given route name\n */\n public getRoute(name: string, params: any = {}) {\n const route = this.routes.find((route) => route.name === name);\n\n if (!route) {\n throw new Error(`Route name \"${name}\" not found`);\n }\n\n let path = route.path;\n\n if (route.path.includes(\":\")) {\n Object.keys(params).forEach((key) => {\n path = path.replace(\":\" + key, params[key]);\n });\n }\n\n return path;\n }\n\n /**\n * Handle the given route\n */\n private handleRoute(route: Route) {\n return async (fastifyRequest: FastifyRequest, fastifyResponse: FastifyReply) => {\n const request = new Request();\n const response = new Response();\n response.setResponse(fastifyResponse);\n request.response = response;\n\n response.request = request;\n\n request.setRequest(fastifyRequest).setRoute(route);\n\n log.info({\n module: \"route\",\n action: route.method + \" \" + route.path.replace(\"/*\", \"\"),\n message: `Starting Request: ${request.id}`,\n context: {\n request,\n response,\n },\n });\n\n const result = await request.execute();\n\n return {\n output: result,\n response,\n request,\n };\n };\n }\n}\n\nexport const router = Router.getInstance();\n\ncontainer.set(\"router\", router);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"router.mjs","names":[],"sources":["../../../../../../../@warlock.js/core/src/router/router.ts"],"sourcesContent":["import proxy, { type FastifyHttpProxyOptions } from \"@fastify/http-proxy\";\nimport fastifyStatic, { type FastifyStaticOptions } from \"@fastify/static\";\nimport concatRoute from \"@mongez/concat-route\";\nimport { ltrim, merge, toCamelCase, trim } from \"@mongez/reinforcements\";\nimport { isEmpty } from \"@mongez/supportive-is\";\nimport { log } from \"@warlock.js/logger\";\nimport type { FastifyReply, FastifyRequest } from \"fastify\";\nimport { container } from \"../container\";\nimport { Request } from \"../http/request\";\nimport { Response } from \"../http/response\";\nimport { type FastifyInstance } from \"../http/server\";\nimport { RouteBuilder } from \"./route-builder\";\nimport { RouteRegistry } from \"./route-registry\";\nimport type {\n GroupedRoutesOptions,\n RequestHandler,\n RequestHandlerType,\n RequestHandlerValidation,\n ResourceMethod,\n Route,\n RouteOptions,\n RouteResource,\n RouterGroupCallback,\n RouterStacks,\n} from \"./types\";\n\nexport class Router {\n /**\n * Routes list\n */\n private routes: Route[] = [];\n\n /**\n * Router Instance\n */\n private static instance: Router;\n\n /**\n * Static paths\n */\n protected staticDirectories: FastifyStaticOptions[] = [];\n\n /**\n * Event listeners\n */\n protected eventListeners: Record<string, ((router: Router, server: FastifyInstance) => void)[]> =\n {};\n\n /**\n * Stacks\n * Stacks will be used for grouping routes to add prefix, name or middleware\n */\n protected stacks: RouterStacks = {\n prefix: [],\n name: [],\n middleware: [],\n };\n\n /**\n * Get router instance\n */\n public static getInstance() {\n if (!Router.instance) {\n Router.instance = new Router();\n }\n\n return Router.instance;\n }\n\n private constructor() {\n //\n }\n\n /**\n * Listen to router before scan\n */\n public beforeScanning(callback: (router: Router, server: FastifyInstance) => void) {\n this.eventListeners.beforeScan = [...(this.eventListeners.beforeScan || []), callback];\n\n return this;\n }\n\n /**\n * Listen to router after scanning\n */\n public afterScanning(callback: (router: Router, server: FastifyInstance) => void) {\n this.eventListeners.afterScanning = [...(this.eventListeners.afterScanning || []), callback];\n\n return this;\n }\n\n /**\n * Redirect path to another path\n */\n public redirect(from: string, to: string, redirectMode: \"temporary\" | \"permanent\" = \"temporary\") {\n return this.get(from, (_request, response) => {\n response.redirect(to, redirectMode === \"temporary\" ? 302 : 301);\n });\n }\n\n /**\n * Server static folder\n */\n public directory(options: FastifyStaticOptions) {\n this.staticDirectories.push(options);\n\n return this;\n }\n\n /**\n * Serve file\n */\n public file(path: string, location: string, cacheTime?: number) {\n return this.get(path, (_request, response) => {\n response.sendFile(location, cacheTime);\n });\n }\n\n /**\n * Serve cached file, it will cache the file to 1 year by default\n */\n public cachedFile(path: string, location: string, cacheTime?: number) {\n return this.get(path, (_request, response) => {\n response.sendCachedFile(location, cacheTime);\n });\n }\n\n /**\n * Serve list of files\n */\n public files(files: Record<string, string>, cacheTime?: number) {\n for (const [path, location] of Object.entries(files)) {\n this.get(path, (_request, response) => {\n response.sendFile(location, cacheTime);\n });\n }\n }\n\n /**\n * Serve list of cached files, it will cache the file to 1 year by default\n */\n public cachedFiles(files: Record<string, string>, cacheTime?: number) {\n for (const [path, location] of Object.entries(files)) {\n this.get(path, (_request, response) => {\n response.sendCachedFile(location, cacheTime);\n });\n }\n }\n\n /**\n * Add proxy route\n */\n public proxy(\n path: string,\n baseUrl: string,\n options?: Omit<FastifyHttpProxyOptions, \"prefix\" | \"upstream\">,\n ): this;\n public proxy(options: FastifyHttpProxyOptions): this;\n public proxy(...args: any[]) {\n this.beforeScanning((_router, server) => {\n if (args.length === 1) {\n server.register(proxy, args[0]);\n } else {\n server.register(proxy, {\n prefix: args[0],\n upstream: args[1],\n ...args[2],\n });\n }\n });\n\n return this;\n }\n\n /**\n * Add route to routes list\n */\n public add(\n method: Route[\"method\"],\n path: string | string[],\n handler: RequestHandlerType,\n options: RouteOptions = {},\n ) {\n if (Array.isArray(path)) {\n path.forEach((p) => this.add(method, p, handler, options));\n return this;\n }\n\n const prefix = this.stacks.prefix.reduce((path, prefix) => {\n return concatRoute(path, prefix);\n }, \"\");\n\n const name = this.stacks.name.reduceRight(\n (name, prefixName) => {\n return trim(prefixName + \".\" + name, \".\");\n },\n options.name || trim(path.replace(/\\//g, \".\"), \".\"),\n );\n\n path = concatRoute(prefix, path);\n\n const middlewarePrecedence = options.middlewarePrecedence || \"after\";\n\n if (middlewarePrecedence === \"before\") {\n options.middleware = [...(options.middleware || []), ...this.stacks.middleware];\n } else {\n options.middleware = [...this.stacks.middleware, ...(options.middleware || [])];\n }\n\n if (Array.isArray(handler)) {\n const [controller, action] = handler;\n\n if (typeof controller[action] !== \"function\") {\n throw new Error(\n `Invalid controller action \"${action}\" for controller \"${controller.constructor.name}\"`,\n );\n }\n\n handler = controller[action].bind(controller) as RequestHandler;\n\n if (!handler.validation) {\n handler.validation = {};\n if (controller[`${action}ValidationSchema`]) {\n handler.validation.schema = controller[`${action}ValidationSchema`]();\n }\n\n if (controller[`${action}Validate`]) {\n handler.validation.validate = controller[`${action}Validate`];\n }\n }\n }\n\n const routeData: Route = {\n method,\n path,\n handler,\n ...options,\n name,\n rateLimit: options.rateLimit,\n $prefix: prefix || \"/\",\n // it must be a new array to avoid modifying the original array\n $prefixStack: [...this.stacks.prefix],\n // Inject source file from stacks if set\n sourceFile: this.stacks.sourceFile || \"\",\n };\n\n if (routeData.name) {\n // check if the name exists\n const route = this.routes.find((route) => route.name === routeData.name);\n\n if (route) {\n // check again if the route name exists with the same method\n if (route.method === routeData.method) {\n throw new Error(`Route name \"${routeData.name}\" already exists`);\n } else {\n routeData.name += `.${routeData.method.toLowerCase()}`;\n }\n }\n }\n\n this.routes.push(routeData);\n\n return this;\n }\n\n /**\n * Add a request that accepts all methods\n */\n public any(path: string, handler: RequestHandlerType, options: RouteOptions = {}) {\n return this.add(\"all\" as Route[\"method\"], path, handler, options);\n }\n\n /**\n * Add get request method\n */\n public get(path: string, handler: RequestHandlerType, options: RouteOptions = {}) {\n return this.add(\"GET\", path, handler, options);\n }\n\n /**\n * Add post request method\n */\n public post(path: string | string[], handler: RequestHandlerType, options: RouteOptions = {}) {\n return this.add(\"POST\", path, handler, options);\n }\n\n /**\n * Add put request method\n */\n public put(path: string, handler: RequestHandlerType, options: RouteOptions = {}) {\n return this.add(\"PUT\", path, handler, options);\n }\n\n /**\n * Add delete request method\n */\n public delete(path: string | string[], handler: RequestHandlerType, options: RouteOptions = {}) {\n return this.add(\"DELETE\", path, handler, options);\n }\n\n /**\n * Add patch request method\n */\n public patch(path: string, handler: RequestHandlerType, options: RouteOptions = {}) {\n return this.add(\"PATCH\", path, handler, options);\n }\n\n /**\n * Add head request method\n */\n public head(path: string, handler: RequestHandlerType, options: RouteOptions = {}) {\n return this.add(\"HEAD\", path, handler, options);\n }\n\n /**\n * Add options request method\n */\n public options(path: string, handler: RequestHandlerType, options: RouteOptions = {}) {\n return this.add(\"OPTIONS\", path, handler, options);\n }\n\n /**\n * Get a chainable route builder for the same route path\n */\n public route(path: string, options: RouteOptions = {}) {\n return new RouteBuilder(this, path, options);\n }\n\n /**\n * Add full restful resource routes\n * This method will generate the following routes:\n * 1. GET /path: list all resources\n * 2. GET /path/:id: get a single resource\n * 3. POST /path: create a new resource\n * 4. PUT /path/:id: update a resource\n * 5. DELETE /path/:id: delete a resource\n * 6. PATCH /path/:id: update a resource partially\n */\n public restfulResource(\n path: string,\n resource: RouteResource,\n options: RouteOptions & {\n only?: ResourceMethod[];\n except?: ResourceMethod[];\n replace?: Partial<Record<ResourceMethod, RequestHandler>> & {\n bulkDelete?: RequestHandler;\n };\n } = {},\n ) {\n return this.prefix(path, () => {\n path = \"\";\n // get base resource name\n const baseResourceName = options.name || toCamelCase(ltrim(path, \"/\"));\n\n // clone the resource so we don't mess up with it\n const routeResource = resource;\n\n const isAcceptableResource = (type: ResourceMethod) => {\n return Boolean(\n // check if the route is not excluded\n (!options.except || !options.except.includes(type)) &&\n // check if the only option is set and the route is included\n (!options.only || options.only.includes(type)),\n );\n };\n\n if (routeResource.list && isAcceptableResource(\"list\")) {\n const resourceName = baseResourceName + \".list\";\n this.get(path, options.replace?.list || routeResource.list.bind(routeResource), {\n ...options,\n name: resourceName,\n restful: true,\n });\n }\n\n if (routeResource.get && isAcceptableResource(\"get\")) {\n const resourceName = baseResourceName + \".single\";\n\n this.get(path + \"/:id\", options.replace?.get || routeResource.get.bind(routeResource), {\n ...options,\n name: resourceName,\n restful: true,\n });\n }\n\n if (routeResource.create && isAcceptableResource(\"create\")) {\n const resourceName = baseResourceName + \".create\";\n\n const handler = options.replace?.create || this.manageValidation(routeResource, \"create\");\n\n this.post(path, handler, {\n ...options,\n name: resourceName,\n restful: true,\n });\n }\n\n if (routeResource.update && isAcceptableResource(\"update\")) {\n const resourceName = baseResourceName + \".update\";\n\n const handler = options.replace?.update || this.manageValidation(routeResource, \"update\");\n\n this.put(path + \"/:id\", handler, {\n ...options,\n name: resourceName,\n restful: true,\n });\n }\n\n if (routeResource.patch && isAcceptableResource(\"patch\")) {\n const resourceName = baseResourceName + \".patch\";\n\n const handler = options.replace?.patch || this.manageValidation(routeResource, \"patch\");\n\n this.patch(path + \"/:id\", handler, {\n ...options,\n name: resourceName,\n restful: true,\n });\n }\n\n if (routeResource.delete && isAcceptableResource(\"delete\")) {\n const resourceName = baseResourceName + \".delete\";\n\n this.delete(\n path + \"/:id\",\n options.replace?.delete || routeResource.delete.bind(routeResource),\n {\n ...options,\n name: resourceName,\n restful: true,\n },\n );\n }\n\n if (routeResource.bulkDelete && isAcceptableResource(\"delete\")) {\n const resourceName = baseResourceName + \".bulkDelete\";\n\n this.delete(\n path,\n options.replace?.bulkDelete || routeResource.bulkDelete.bind(routeResource),\n {\n ...options,\n name: resourceName,\n restful: true,\n },\n );\n }\n\n return this;\n });\n }\n\n /**\n * Group routes with options\n */\n public group(options: GroupedRoutesOptions, callback: RouterGroupCallback) {\n const {\n prefix,\n // name must always be defined because\n // if there are multiple groups without name\n // they might generate the same route name\n // thus causing an error\n // in this case we need always to make sure that\n // the name is always defined.\n name = prefix ? trim(prefix.replace(/\\//g, \".\"), \".\") : undefined,\n middleware,\n } = options;\n\n if (prefix) {\n this.stacks.prefix.push(prefix);\n }\n\n if (name) {\n this.stacks.name.push(name);\n }\n\n if (middleware) {\n this.stacks.middleware.push(...middleware);\n }\n\n try {\n callback();\n } finally {\n // Always pop/splice this group's stacks, even if the callback throws,\n // so a throwing group never leaks state onto the process-global singleton.\n if (prefix) {\n this.stacks.prefix.pop();\n }\n\n if (name) {\n this.stacks.name.pop();\n }\n\n if (middleware) {\n this.stacks.middleware.splice(\n this.stacks.middleware.length - middleware.length,\n middleware.length,\n );\n }\n }\n\n return this;\n }\n\n /**\n * Add prefix to all routes in the given callback\n */\n public prefix(prefix: string, callback: () => void) {\n return this.group({ prefix }, callback);\n }\n\n /**\n * Add API version prefix to all routes in the given callback\n * Automatically formats the version as /v{version}\n * @example\n * router.version(\"1\", () => {\n * router.get(\"/users\", getUsersV1); // /v1/users\n * });\n *\n * router.version(\"2\", () => {\n * router.get(\"/users\", getUsersV2); // /v2/users\n * });\n */\n public version(version: string | number, callback: () => void) {\n return this.prefix(`/v${version}`, callback);\n }\n\n /**\n * Wrap route additions with a source file path\n * Used for tracking which routes come from which file (for HMR)\n * @param sourceFile Relative path to the source file (e.g., \"src/app/users/routes.ts\")\n * @param callback Function that adds routes (will have sourceFile injected)\n */\n public async withSourceFile<T = any>(\n sourceFile: string,\n callback: () => T | Promise<T>,\n ): Promise<T | undefined> {\n // Set source file in stacks\n this.stacks.sourceFile = sourceFile;\n\n try {\n // Execute callback (routes added here will have sourceFile injected)\n return await callback();\n } catch (error) {\n // Log loudly, then RETHROW. Swallowing here silently dropped a whole\n // route file (duplicate name, invalid action, import error) so the\n // surface 404'd with no boot error. The caller decides what a throw\n // means: at boot it aborts the boot, during HMR the dev server's\n // batch-reload handler catches it, prints it, and keeps serving.\n log.error({\n module: \"router\",\n action: \"registerRoutes\",\n message: `Failed to register routes from \"${sourceFile}\"`,\n context: { sourceFile, error },\n });\n\n throw error;\n } finally {\n // Always clear source file from stacks so a throwing file never leaks\n // its sourceFile onto the process-global singleton.\n delete this.stacks.sourceFile;\n }\n }\n\n /**\n * Remove all routes that belong to a specific source file\n * Used when reloading routes files via HMR\n * @param sourceFile Relative path to the source file\n */\n public removeRoutesBySourceFile(sourceFile: string): void {\n this.routes = this.routes.filter((route) => route.sourceFile !== sourceFile);\n }\n\n /**\n * Manage validation system for the given resource\n */\n private manageValidation(resource: RouteResource, method: \"create\" | \"update\" | \"patch\") {\n const handler = resource[method]?.bind(resource) as RequestHandler;\n\n const methodValidation = resource?.validation?.[method];\n\n if (method === \"patch\") {\n handler.validation = methodValidation;\n\n if (handler.validation?.validate) {\n handler.validation.validate = handler.validation.validate.bind(resource);\n }\n\n if (resource.validation?.patch) {\n handler.validation = merge(resource.validation.patch, handler.validation);\n }\n\n return handler;\n }\n\n if (!resource.validation || (!methodValidation && !resource.validation.all)) return handler;\n\n if (resource.validation.all) {\n const validationMethods = {\n all: resource?.validation?.all?.validate,\n [method]: methodValidation?.validate,\n };\n\n const validation: RequestHandlerValidation = {};\n\n if (resource.validation.all.schema || methodValidation?.schema) {\n if (!methodValidation?.schema && resource.validation.all.schema) {\n // Case 2: Only all.schema exists - clone it for this method\n validation.schema = resource.validation.all.schema;\n } else if (methodValidation?.schema && resource.validation.all.schema) {\n // Case 3: Both exist - merge them (all is base, method overrides)\n validation.schema = resource.validation.all.schema.merge(methodValidation.schema);\n } else if (methodValidation?.schema && !resource.validation.all.schema) {\n // Case 1: Only method schema exists - use it directly\n validation.schema = methodValidation.schema;\n }\n // Case 4: Neither exists - handled by outer if being false\n }\n\n if (validationMethods.all || validationMethods[method]) {\n validation.validate = async (request: Request, response: Response) => {\n if (validationMethods.all) {\n const output = await validationMethods.all.call(resource, request, response);\n\n if (output) return output;\n }\n\n if (validationMethods[method]) {\n return await validationMethods[method]?.call(resource, request, response);\n }\n\n return;\n };\n }\n\n if (!isEmpty(validation)) {\n handler.validation = validation;\n }\n } else {\n handler.validation = resource.validation[method];\n\n if (handler.validation?.validate) {\n handler.validation.validate = handler.validation.validate.bind(resource);\n }\n }\n\n return handler;\n }\n\n /**\n * Get all routes list\n */\n public list() {\n return this.routes;\n }\n\n /**\n * Number of routes currently registered on the singleton.\n *\n * Used as a readiness signal: a successful boot that ends up with zero\n * routes almost always means a route module failed to register silently\n * (see `withSourceFile`), so callers can surface that instead of letting\n * the whole surface 404.\n */\n public routeCount(): number {\n return this.routes.length;\n }\n\n /**\n * Register routes to the server\n */\n public scan(server: FastifyInstance) {\n this.eventListeners.beforeScan?.forEach((callback) => callback(this, server));\n\n this.routes.forEach((route) => {\n const requestMethod = route.method.toLowerCase();\n const requestMethodFunction = server[requestMethod].bind(server);\n\n const options = {\n ...route.serverOptions,\n config: {\n ...route.serverOptions?.config,\n ...(route.rateLimit && { rateLimit: route.rateLimit }),\n },\n };\n\n requestMethodFunction(\n route.path,\n options,\n async (baseRequest: FastifyRequest, reply: FastifyReply) => {\n const { output, response } = await this.handleRoute(route)(baseRequest, reply);\n\n return output || response.baseResponse;\n },\n );\n });\n\n for (const directoryOptions of this.staticDirectories) {\n server.register(fastifyStatic, {\n ...directoryOptions,\n decorateReply: false,\n });\n }\n\n this.eventListeners.afterScanning?.forEach((callback) => callback(this, server));\n }\n\n /**\n * Scan routes for the development server\n * Uses wildcard routing with find-my-way for HMR support\n */\n public scanDevServer(server: FastifyInstance) {\n this.eventListeners.beforeScan?.forEach((callback) => callback(this, server));\n\n // Shared handler for wildcard routing\n const wildcardHandler = async (fastifyRequest: FastifyRequest, fastifyReply: FastifyReply) => {\n // Initialize route registry once (will be rebuilt on HMR via rebuildRouteRegistry)\n const routeRegistry = new RouteRegistry();\n\n routeRegistry.register(this.routes);\n // Find matching route using find-my-way\n const match = routeRegistry.find(fastifyRequest.method, fastifyRequest.url);\n\n // No match found - return 404\n if (!match) {\n return fastifyReply.code(404).send({\n error: \"Route not found\",\n path: fastifyRequest.url,\n method: fastifyRequest.method,\n });\n }\n\n // Inject extracted params into the request\n fastifyRequest.params = match.params;\n\n try {\n // Call the matched route handler\n const { output, response } = await this.handleRoute(match.route)(\n fastifyRequest,\n fastifyReply,\n );\n\n return output || response.baseResponse;\n } catch (error) {\n console.log(error);\n throw error;\n }\n };\n\n // Register wildcard route for all methods EXCEPT OPTIONS (to avoid conflict with CORS)\n // OPTIONS is handled by @fastify/cors plugin for preflight requests\n const methods = [\"GET\", \"POST\", \"PUT\", \"DELETE\", \"PATCH\"] as const;\n for (const method of methods) {\n server.route({\n method,\n url: \"*\",\n handler: wildcardHandler,\n });\n }\n\n // Register static directories\n for (const directoryOptions of this.staticDirectories) {\n server.register(fastifyStatic, {\n ...directoryOptions,\n decorateReply: false,\n });\n }\n\n this.eventListeners.afterScanning?.forEach((callback) => callback(this, server));\n }\n\n /**\n * Get the route path for the given route name\n */\n public getRoute(name: string, params: any = {}) {\n const route = this.routes.find((route) => route.name === name);\n\n if (!route) {\n throw new Error(`Route name \"${name}\" not found`);\n }\n\n let path = route.path;\n\n if (route.path.includes(\":\")) {\n Object.keys(params).forEach((key) => {\n path = path.replace(\":\" + key, params[key]);\n });\n }\n\n return path;\n }\n\n /**\n * Handle the given route\n */\n private handleRoute(route: Route) {\n return async (fastifyRequest: FastifyRequest, fastifyResponse: FastifyReply) => {\n const request = new Request();\n const response = new Response();\n response.setResponse(fastifyResponse);\n request.response = response;\n\n response.request = request;\n\n request.setRequest(fastifyRequest).setRoute(route);\n\n log.info({\n module: \"route\",\n action: route.method + \" \" + route.path.replace(\"/*\", \"\"),\n message: `Starting Request: ${request.id}`,\n context: {\n request,\n response,\n },\n });\n\n const result = await request.execute();\n\n return {\n output: result,\n response,\n request,\n };\n };\n }\n}\n\nexport const router = Router.getInstance();\n\ncontainer.set(\"router\", router);\n"],"mappings":"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"}
|
package/esm/utils/paths.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import config from "@mongez/config";
|
|
2
2
|
import path from "path";
|
|
3
3
|
|
|
4
4
|
//#region ../@warlock.js/core/src/utils/paths.ts
|
|
@@ -28,7 +28,7 @@ function storagePath(relativePath = "") {
|
|
|
28
28
|
* If no path is given, it will return the absolute path to the uploads folder
|
|
29
29
|
*/
|
|
30
30
|
function uploadsPath(relativePath = "") {
|
|
31
|
-
const configPath =
|
|
31
|
+
const configPath = config.get("uploads.root");
|
|
32
32
|
if (!configPath) return rootPath("storage", "uploads", relativePath);
|
|
33
33
|
return typeof configPath === "function" ? configPath(relativePath) : path.resolve(configPath, relativePath);
|
|
34
34
|
}
|
package/esm/utils/paths.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.mjs","names":[
|
|
1
|
+
{"version":3,"file":"paths.mjs","names":[],"sources":["../../../../../../../@warlock.js/core/src/utils/paths.ts"],"sourcesContent":["import config from \"@mongez/config\";\r\nimport path from \"path\";\r\n\r\n/**\r\n * Get root path or join the given paths to the root path\r\n */\r\nexport function rootPath(...paths: string[]) {\r\n return path.resolve(process.cwd(), ...paths);\r\n}\r\n\r\n/**\r\n * Get src directory path or join the given paths to the src directory path\r\n */\r\nexport function srcPath(...paths: string[]) {\r\n return rootPath(\"src\", ...paths);\r\n}\r\n\r\n/**\r\n * Get the absolute path to the storage folder to the given path\r\n *\r\n * If no path is given, it will return the absolute path to the storage folder\r\n */\r\nexport function storagePath(relativePath = \"\") {\r\n return rootPath(\"storage\", relativePath);\r\n}\r\n\r\n/**\r\n * Get the absolute path to the uploads folder to the given path\r\n *\r\n * If no path is given, it will return the absolute path to the uploads folder\r\n */\r\nexport function uploadsPath(relativePath = \"\") {\r\n const configPath = config.get(\"uploads.root\");\r\n if (!configPath) {\r\n return rootPath(\"storage\", \"uploads\", relativePath);\r\n }\r\n\r\n return typeof configPath === \"function\"\r\n ? configPath(relativePath)\r\n : path.resolve(configPath, relativePath);\r\n}\r\n\r\n/**\r\n * Get the absolute path to the public folder to the given path\r\n *\r\n * If no path is given, it will return the absolute path to the public folder\r\n */\r\nexport function publicPath(relativePath = \"\") {\r\n return rootPath(\"public\", relativePath);\r\n}\r\n\r\n/**\r\n * Get the absolute path to the cache folder to the given path\r\n *\r\n * If no path is given, it will return the absolute path to the cache folder\r\n */\r\nexport function cachePath(relativePath = \"\") {\r\n return rootPath(\"storage\", \"cache\", relativePath);\r\n}\r\n\r\n/**\r\n * App path\r\n */\r\nexport function appPath(relativePath = \"\") {\r\n return rootPath(\"src/app\", relativePath);\r\n}\r\n\r\n/**\r\n * Get logs directory path\r\n */\r\nexport function logsPath(relativePath = \"\") {\r\n return rootPath(\"storage/logs\", relativePath);\r\n}\r\n\r\n/**\r\n * Get a temp path\r\n */\r\nexport function tempPath(relativePath = \"\") {\r\n return rootPath(\"storage/tmp\", relativePath);\r\n}\r\n\r\n/**\r\n * Remove any invalid characters from the file path using regex\r\n * It should accept any language character, numbers, and the following characters: _ - .\r\n */\r\nconst invalidCharsRegex = /[<>:\"/\\\\|?*]/g; // Regex to match invalid characters\r\nexport function sanitizePath(filePath: string) {\r\n return filePath.replace(invalidCharsRegex, \"\"); // Replace invalid characters with an empty string\r\n}\r\n\r\n/**\r\n * Warlock path\r\n * PLEASE DO NOT add any files in this directory as it may be deleted\r\n */\r\nexport function warlockPath(...path: string[]) {\r\n return rootPath(\".warlock\", ...path);\r\n}\r\n\r\n/**\r\n * Get config directory path\r\n */\r\nexport function configPath(...path: string[]) {\r\n return rootPath(\"src/config\", ...path);\r\n}\r\n\r\nexport const paths = {\r\n root: rootPath,\r\n src: srcPath,\r\n storage: storagePath,\r\n logs: logsPath,\r\n uploads: uploadsPath,\r\n public: publicPath,\r\n cache: cachePath,\r\n app: appPath,\r\n temp: tempPath,\r\n warlock: warlockPath,\r\n config: configPath,\r\n sanitize: sanitizePath,\r\n};\r\n"],"mappings":";;;;;;;AAMA,SAAgB,SAAS,GAAG,OAAiB;CAC3C,OAAO,KAAK,QAAQ,QAAQ,IAAI,GAAG,GAAG,KAAK;AAC7C;;;;AAKA,SAAgB,QAAQ,GAAG,OAAiB;CAC1C,OAAO,SAAS,OAAO,GAAG,KAAK;AACjC;;;;;;AAOA,SAAgB,YAAY,eAAe,IAAI;CAC7C,OAAO,SAAS,WAAW,YAAY;AACzC;;;;;;AAOA,SAAgB,YAAY,eAAe,IAAI;CAC7C,MAAM,aAAa,OAAO,IAAI,cAAc;CAC5C,IAAI,CAAC,YACH,OAAO,SAAS,WAAW,WAAW,YAAY;CAGpD,OAAO,OAAO,eAAe,aACzB,WAAW,YAAY,IACvB,KAAK,QAAQ,YAAY,YAAY;AAC3C;;;;;;AAOA,SAAgB,WAAW,eAAe,IAAI;CAC5C,OAAO,SAAS,UAAU,YAAY;AACxC;;;;;;AAOA,SAAgB,UAAU,eAAe,IAAI;CAC3C,OAAO,SAAS,WAAW,SAAS,YAAY;AAClD;;;;AAKA,SAAgB,QAAQ,eAAe,IAAI;CACzC,OAAO,SAAS,WAAW,YAAY;AACzC;;;;AAKA,SAAgB,SAAS,eAAe,IAAI;CAC1C,OAAO,SAAS,gBAAgB,YAAY;AAC9C;;;;AAKA,SAAgB,SAAS,eAAe,IAAI;CAC1C,OAAO,SAAS,eAAe,YAAY;AAC7C;;;;;AAMA,MAAM,oBAAoB;AAC1B,SAAgB,aAAa,UAAkB;CAC7C,OAAO,SAAS,QAAQ,mBAAmB,EAAE;AAC/C;;;;;AAMA,SAAgB,YAAY,GAAG,MAAgB;CAC7C,OAAO,SAAS,YAAY,GAAG,IAAI;AACrC;;;;AAKA,SAAgB,WAAW,GAAG,MAAgB;CAC5C,OAAO,SAAS,cAAc,GAAG,IAAI;AACvC;AAEA,MAAa,QAAQ;CACnB,MAAM;CACN,KAAK;CACL,SAAS;CACT,MAAM;CACN,SAAS;CACT,QAAQ;CACR,OAAO;CACP,KAAK;CACL,MAAM;CACN,SAAS;CACT,QAAQ;CACR,UAAU;AACZ"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { v } from "@warlock.js/seal";
|
|
2
|
-
import
|
|
2
|
+
import config from "@mongez/config";
|
|
3
3
|
import { log } from "@warlock.js/logger";
|
|
4
4
|
import { merge } from "@mongez/reinforcements";
|
|
5
5
|
|
|
@@ -40,7 +40,7 @@ async function validateAll(validation, request, response) {
|
|
|
40
40
|
if (validation.validate) {
|
|
41
41
|
const result = await validation.validate(request, response);
|
|
42
42
|
if (result) {
|
|
43
|
-
if (!response.statusCode) response.setStatusCode(
|
|
43
|
+
if (!response.statusCode) response.setStatusCode(config.get("validation.responseStatus", 400));
|
|
44
44
|
log.info("validation", "failed", "Validation failed");
|
|
45
45
|
return result;
|
|
46
46
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateAll.mjs","names":[
|
|
1
|
+
{"version":3,"file":"validateAll.mjs","names":[],"sources":["../../../../../../../@warlock.js/core/src/validation/validateAll.ts"],"sourcesContent":["import config from \"@mongez/config\";\nimport { merge } from \"@mongez/reinforcements\";\nimport { log } from \"@warlock.js/logger\";\nimport { v } from \"@warlock.js/seal\";\nimport type { Request, Response } from \"../http\";\nimport type { RequestHandlerValidation, Route } from \"../router\";\n\nfunction resolveDataToParse(validating: RequestHandlerValidation[\"validating\"], request: Request) {\n if (!validating || validating.length === 0) return request.allExceptParams();\n\n let data: any = {};\n\n for (const validatingType of validating) {\n if (validatingType === \"body\") {\n data = merge(data, request.body);\n }\n\n if (validatingType === \"query\") {\n data = merge(data, request.query);\n }\n\n if (validatingType === \"params\") {\n data = merge(data, request.params);\n }\n\n if (validatingType === \"headers\") {\n data = merge(data, request.headers);\n }\n }\n\n return data;\n}\n\n/**\n * Validate the request route\n */\nexport async function validateAll(\n validation: Route[\"handler\"][\"validation\"],\n request: Request,\n response: Response,\n) {\n if (!validation) return;\n\n log.info(\"validation\", \"started\", \"Start validating the request\");\n\n if (validation.schema) {\n log.info(\"validation\", \"schema\", \"Validating request schema\");\n try {\n const data = resolveDataToParse(validation.validating, request);\n const result = await v.validate(validation.schema, data);\n\n if (result.data && result.isValid) {\n request.setValidatedData(result.data);\n }\n\n if (!result.isValid) {\n log.warn(\"validation\", \"schema\", \"Schema Validation failed\");\n return response.failedSchema(result);\n }\n\n log.success(\"validation\", \"schema\", \"Schema Validation passed\");\n } catch (error) {\n log.warn(\"app.validation\", \"error\", error);\n throw error;\n }\n }\n\n if (validation.validate) {\n const result = await validation.validate(request, response);\n\n // if there is a result, it means it failed\n if (result) {\n // check if there is no response status code, then set it to config value or 400 as default\n if (!response.statusCode) {\n response.setStatusCode(config.get(\"validation.responseStatus\", 400));\n }\n\n log.info(\"validation\", \"failed\", \"Validation failed\");\n\n return result;\n }\n\n log.info(\"validation\", \"passed\", \"Validation passed\");\n }\n}\n"],"mappings":";;;;;;AAOA,SAAS,mBAAmB,YAAoD,SAAkB;CAChG,IAAI,CAAC,cAAc,WAAW,WAAW,GAAG,OAAO,QAAQ,gBAAgB;CAE3E,IAAI,OAAY,CAAC;CAEjB,KAAK,MAAM,kBAAkB,YAAY;EACvC,IAAI,mBAAmB,QACrB,OAAO,MAAM,MAAM,QAAQ,IAAI;EAGjC,IAAI,mBAAmB,SACrB,OAAO,MAAM,MAAM,QAAQ,KAAK;EAGlC,IAAI,mBAAmB,UACrB,OAAO,MAAM,MAAM,QAAQ,MAAM;EAGnC,IAAI,mBAAmB,WACrB,OAAO,MAAM,MAAM,QAAQ,OAAO;CAEtC;CAEA,OAAO;AACT;;;;AAKA,eAAsB,YACpB,YACA,SACA,UACA;CACA,IAAI,CAAC,YAAY;CAEjB,IAAI,KAAK,cAAc,WAAW,8BAA8B;CAEhE,IAAI,WAAW,QAAQ;EACrB,IAAI,KAAK,cAAc,UAAU,2BAA2B;EAC5D,IAAI;GACF,MAAM,OAAO,mBAAmB,WAAW,YAAY,OAAO;GAC9D,MAAM,SAAS,MAAM,EAAE,SAAS,WAAW,QAAQ,IAAI;GAEvD,IAAI,OAAO,QAAQ,OAAO,SACxB,QAAQ,iBAAiB,OAAO,IAAI;GAGtC,IAAI,CAAC,OAAO,SAAS;IACnB,IAAI,KAAK,cAAc,UAAU,0BAA0B;IAC3D,OAAO,SAAS,aAAa,MAAM;GACrC;GAEA,IAAI,QAAQ,cAAc,UAAU,0BAA0B;EAChE,SAAS,OAAO;GACd,IAAI,KAAK,kBAAkB,SAAS,KAAK;GACzC,MAAM;EACR;CACF;CAEA,IAAI,WAAW,UAAU;EACvB,MAAM,SAAS,MAAM,WAAW,SAAS,SAAS,QAAQ;EAG1D,IAAI,QAAQ;GAEV,IAAI,CAAC,SAAS,YACZ,SAAS,cAAc,OAAO,IAAI,6BAA6B,GAAG,CAAC;GAGrE,IAAI,KAAK,cAAc,UAAU,mBAAmB;GAEpD,OAAO;EACT;EAEA,IAAI,KAAK,cAAc,UAAU,mBAAmB;CACtD;AACF"}
|