@warlock.js/core 5.5.0 → 5.7.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 (171) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/esm/application/app.d.mts.map +1 -1
  3. package/esm/application/app.mjs +7 -1
  4. package/esm/application/app.mjs.map +1 -1
  5. package/esm/benchmark/profiler.d.mts.map +1 -1
  6. package/esm/benchmark/profiler.mjs +4 -3
  7. package/esm/benchmark/profiler.mjs.map +1 -1
  8. package/esm/cli/cli-commands.manager.mjs +10 -7
  9. package/esm/cli/cli-commands.manager.mjs.map +1 -1
  10. package/esm/cli/cli-commands.utils.mjs.map +1 -1
  11. package/esm/cli/commands/doctor/checks/optional-peers.check.mjs.map +1 -1
  12. package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs.map +1 -1
  13. package/esm/cli/commands/generate/generators/column-dsl-parser.mjs.map +1 -1
  14. package/esm/cli/commands/generate/generators/migration.generator.mjs.map +1 -1
  15. package/esm/cli/commands/routes/format-routes-table.mjs +3 -3
  16. package/esm/cli/commands/routes/format-routes-table.mjs.map +1 -1
  17. package/esm/cli/commands/routes/route-row.mjs.map +1 -1
  18. package/esm/cli/commands/routes.command.mjs.map +1 -1
  19. package/esm/cli/framework-cli-commands.mjs.map +1 -1
  20. package/esm/cli/parse-cli-args.mjs +1 -0
  21. package/esm/cli/parse-cli-args.mjs.map +1 -1
  22. package/esm/cli/string-similarity.mjs +13 -4
  23. package/esm/cli/string-similarity.mjs.map +1 -1
  24. package/esm/commands/cli-command.d.mts.map +1 -1
  25. package/esm/commands/cli-command.mjs +5 -2
  26. package/esm/commands/cli-command.mjs.map +1 -1
  27. package/esm/config/config-loader.mjs +3 -1
  28. package/esm/config/config-loader.mjs.map +1 -1
  29. package/esm/config/locale-configuration.mjs +11 -1
  30. package/esm/config/locale-configuration.mjs.map +1 -1
  31. package/esm/container/container-instance-registry.mjs +40 -0
  32. package/esm/container/container-instance-registry.mjs.map +1 -0
  33. package/esm/container/index.d.mts +11 -0
  34. package/esm/container/index.d.mts.map +1 -1
  35. package/esm/container/index.mjs +11 -0
  36. package/esm/container/index.mjs.map +1 -1
  37. package/esm/database/drop-tables-action.mjs.map +1 -1
  38. package/esm/database/migrate-action.mjs.map +1 -1
  39. package/esm/database/seed-command-action.mjs.map +1 -1
  40. package/esm/dev-server/dependency-graph.d.mts.map +1 -1
  41. package/esm/dev-server/dependency-graph.mjs +2 -1
  42. package/esm/dev-server/dependency-graph.mjs.map +1 -1
  43. package/esm/dev-server/dev-logger.mjs +7 -5
  44. package/esm/dev-server/dev-logger.mjs.map +1 -1
  45. package/esm/dev-server/file-event-handler.mjs.map +1 -1
  46. package/esm/dev-server/files-orchestrator.mjs +1 -1
  47. package/esm/dev-server/files-orchestrator.mjs.map +1 -1
  48. package/esm/dev-server/layer-executor.mjs.map +1 -1
  49. package/esm/dev-server/loader/build-transpile-init.mjs.map +1 -1
  50. package/esm/dev-server/loader/load-hook.mjs.map +1 -1
  51. package/esm/dev-server/loader/register-loader.mjs.map +1 -1
  52. package/esm/dev-server/loader/resolve-hook.mjs.map +1 -1
  53. package/esm/dev-server/loader/transpile-cache.mjs.map +1 -1
  54. package/esm/dev-server/module-loader.mjs.map +1 -1
  55. package/esm/dev-server/parse-imports.mjs +22 -8
  56. package/esm/dev-server/parse-imports.mjs.map +1 -1
  57. package/esm/dev-server/type-generator.mjs.map +1 -1
  58. package/esm/dev-server/types.d.mts.map +1 -1
  59. package/esm/dev-server/utils.mjs.map +1 -1
  60. package/esm/encryption/encrypt.mjs +1 -0
  61. package/esm/encryption/encrypt.mjs.map +1 -1
  62. package/esm/errors/container-key-missing-error.mjs +28 -0
  63. package/esm/errors/container-key-missing-error.mjs.map +1 -0
  64. package/esm/errors/unknown-locale-error.mjs +28 -0
  65. package/esm/errors/unknown-locale-error.mjs.map +1 -0
  66. package/esm/generations/add-command.action.mjs +8 -2
  67. package/esm/generations/add-command.action.mjs.map +1 -1
  68. package/esm/generations/features/access.feature.mjs.map +1 -1
  69. package/esm/generations/features/ai-anthropic.feature.mjs.map +1 -1
  70. package/esm/generations/features/ai-bedrock.feature.mjs.map +1 -1
  71. package/esm/generations/features/ai-google.feature.mjs.map +1 -1
  72. package/esm/generations/features/ai-ollama.feature.mjs.map +1 -1
  73. package/esm/generations/features/ai-openai.feature.mjs.map +1 -1
  74. package/esm/generations/features/ai-panoptic.feature.mjs.map +1 -1
  75. package/esm/generations/features/ai-tools.feature.mjs.map +1 -1
  76. package/esm/generations/features/ai-workspace.feature.mjs.map +1 -1
  77. package/esm/generations/features/ai.feature.mjs.map +1 -1
  78. package/esm/generations/features/herald.feature.mjs.map +1 -1
  79. package/esm/generations/features/notifications.feature.mjs.map +1 -1
  80. package/esm/generations/features/scheduler.feature.mjs.map +1 -1
  81. package/esm/generations/features/shared/patch-tsconfig-include.mjs.map +1 -1
  82. package/esm/generations/features/shared/relocate-conflicting-home-route.mjs +6 -1
  83. package/esm/generations/features/shared/relocate-conflicting-home-route.mjs.map +1 -1
  84. package/esm/generations/features/tailwind.feature.mjs.map +1 -1
  85. package/esm/generations/features/types.mjs.map +1 -1
  86. package/esm/generations/features/web.feature.mjs.map +1 -1
  87. package/esm/http/context/request-memo.mjs.map +1 -1
  88. package/esm/http/middleware/cache-response-middleware.d.mts.map +1 -1
  89. package/esm/http/middleware/cache-response-middleware.mjs.map +1 -1
  90. package/esm/http/middleware/concurrency-limit.middleware.mjs.map +1 -1
  91. package/esm/http/middleware/idempotency.middleware.d.mts.map +1 -1
  92. package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
  93. package/esm/http/middleware/maintenance.middleware.mjs +1 -2
  94. package/esm/http/middleware/maintenance.middleware.mjs.map +1 -1
  95. package/esm/http/middleware/max-body-size.middleware.mjs.map +1 -1
  96. package/esm/http/middleware/rate-limit.middleware.mjs.map +1 -1
  97. package/esm/http/middleware/utils/cidr-match.d.mts.map +1 -1
  98. package/esm/http/middleware/utils/cidr-match.mjs +1 -0
  99. package/esm/http/middleware/utils/cidr-match.mjs.map +1 -1
  100. package/esm/http/port-preflight.d.mts.map +1 -1
  101. package/esm/http/port-preflight.mjs.map +1 -1
  102. package/esm/http/request.d.mts.map +1 -1
  103. package/esm/http/request.mjs +16 -9
  104. package/esm/http/request.mjs.map +1 -1
  105. package/esm/http/response.d.mts +38 -0
  106. package/esm/http/response.d.mts.map +1 -1
  107. package/esm/http/response.mjs +47 -0
  108. package/esm/http/response.mjs.map +1 -1
  109. package/esm/http/server.d.mts.map +1 -1
  110. package/esm/http/server.mjs.map +1 -1
  111. package/esm/http/types.d.mts.map +1 -1
  112. package/esm/image/image.d.mts.map +1 -1
  113. package/esm/image/image.mjs.map +1 -1
  114. package/esm/mail/send-mail.mjs.map +1 -1
  115. package/esm/production/build-contributions.mjs.map +1 -1
  116. package/esm/production/bundle-framework-dependencies.mjs +152 -0
  117. package/esm/production/bundle-framework-dependencies.mjs.map +1 -0
  118. package/esm/production/production-builder.mjs +30 -3
  119. package/esm/production/production-builder.mjs.map +1 -1
  120. package/esm/production/production-supervisor.mjs.map +1 -1
  121. package/esm/production/tsconfig-path-aliases.mjs +99 -0
  122. package/esm/production/tsconfig-path-aliases.mjs.map +1 -0
  123. package/esm/react/index.d.mts.map +1 -1
  124. package/esm/react/index.mjs.map +1 -1
  125. package/esm/repositories/adapters/cascade/filter-applicator.mjs +4 -2
  126. package/esm/repositories/adapters/cascade/filter-applicator.mjs.map +1 -1
  127. package/esm/repositories/contracts/query-builder.contract.d.mts.map +1 -1
  128. package/esm/repositories/contracts/types.d.mts.map +1 -1
  129. package/esm/resource/resource-field-builder.d.mts.map +1 -1
  130. package/esm/resource/resource-field-builder.mjs.map +1 -1
  131. package/esm/resource/types.d.mts.map +1 -1
  132. package/esm/router/positional-handler-diagnostics.d.mts.map +1 -1
  133. package/esm/router/positional-handler-diagnostics.mjs +9 -3
  134. package/esm/router/positional-handler-diagnostics.mjs.map +1 -1
  135. package/esm/router/route-registry.mjs +1 -1
  136. package/esm/router/route-registry.mjs.map +1 -1
  137. package/esm/router/router.d.mts.map +1 -1
  138. package/esm/router/router.mjs +1 -2
  139. package/esm/router/router.mjs.map +1 -1
  140. package/esm/router/types.d.mts.map +1 -1
  141. package/esm/storage/drivers/cloud-driver.d.mts.map +1 -1
  142. package/esm/storage/drivers/cloud-driver.mjs.map +1 -1
  143. package/esm/storage/scoped-storage.d.mts.map +1 -1
  144. package/esm/storage/scoped-storage.mjs +1 -0
  145. package/esm/storage/scoped-storage.mjs.map +1 -1
  146. package/esm/storage/storage.d.mts.map +1 -1
  147. package/esm/storage/storage.mjs +6 -2
  148. package/esm/storage/storage.mjs.map +1 -1
  149. package/esm/storage/types.d.mts.map +1 -1
  150. package/esm/storage/utils/contain-path.mjs.map +1 -1
  151. package/esm/storage/utils/safe-fetch.d.mts.map +1 -1
  152. package/esm/storage/utils/safe-fetch.mjs +6 -1
  153. package/esm/storage/utils/safe-fetch.mjs.map +1 -1
  154. package/esm/tests/start-http-development-server.d.mts.map +1 -1
  155. package/esm/tests/start-http-development-server.mjs.map +1 -1
  156. package/esm/tests/test-lifecycle-state.mjs.map +1 -1
  157. package/esm/tests/test-setup-timeout.mjs.map +1 -1
  158. package/esm/tests/vitest-setup.d.mts.map +1 -1
  159. package/esm/tests/vitest-setup.mjs.map +1 -1
  160. package/esm/use-cases/use-cases-registry.d.mts.map +1 -1
  161. package/esm/use-cases/use-cases-registry.mjs.map +1 -1
  162. package/esm/utils/app-log.mjs.map +1 -1
  163. package/esm/utils/queue.mjs.map +1 -1
  164. package/esm/utils/sleep.mjs.map +1 -1
  165. package/esm/utils/version-compare.d.mts.map +1 -1
  166. package/esm/utils/version-compare.mjs +12 -4
  167. package/esm/utils/version-compare.mjs.map +1 -1
  168. package/esm/validation/plugins/database-plugin.mjs.map +1 -1
  169. package/esm/vite/lower-stage3-decorators.mjs +1 -0
  170. package/esm/vite/lower-stage3-decorators.mjs.map +1 -1
  171. package/package.json +12 -12
@@ -1 +1 @@
1
- {"version":3,"file":"filter-applicator.mjs","names":[],"sources":["../../../../../../../../../core/src/repositories/adapters/cascade/filter-applicator.ts"],"sourcesContent":["import type {\n QueryBuilderContract as CascadeQueryBuilder,\n QueryBuilderContract,\n} from \"@warlock.js/cascade\";\nimport type { FilterOptions, FilterRule, FilterRules } from \"../../contracts\";\n\n/**\n * Applies repository filters to a Cascade-Next query builder\n * Translates repository filter rules into Cascade query builder method calls\n */\nexport class FilterApplicator {\n /**\n * Apply filters to a Cascade query builder\n *\n * @param query - Cascade query builder instance\n * @param filters - Filter structure defining how to filter\n * @param data - Data containing filter values\n * @param options - Additional filter options (date formats, etc.)\n */\n public apply(\n query: CascadeQueryBuilder<any>,\n filters: FilterRules,\n data: any,\n options: FilterOptions,\n ): void {\n for (const key in filters) {\n const value = data[key];\n if (value === undefined) continue;\n\n const rule = this.parseFilterRule(key, filters[key]);\n this.applyFilterRule(query, rule, value, data, options);\n }\n }\n\n /**\n * Parse a filter rule into a structured format\n */\n private parseFilterRule(key: string, rule: FilterRule) {\n // Handle custom function\n if (typeof rule === \"function\") {\n return { type: \"function\", fn: rule, column: key, key };\n }\n\n // Handle array format: [\"operator\"] or [\"operator\", \"column\"] or [\"operator\", [\"col1\", \"col2\"]]\n if (Array.isArray(rule)) {\n const [operator, target] = rule;\n\n if (target === undefined) {\n return { type: operator, column: key, columns: undefined, key };\n }\n\n if (Array.isArray(target)) {\n return { type: operator, column: undefined, columns: target, key };\n }\n\n return { type: operator, column: target, columns: undefined, key };\n }\n\n // Handle simple operator string\n return { type: rule, column: key, columns: undefined, key };\n }\n\n /**\n * Apply a single filter rule to the query\n */\n private applyFilterRule(\n query: CascadeQueryBuilder<any>,\n rule: any,\n value: any,\n data: any,\n options: FilterOptions,\n ): void {\n // 1. Custom function filter\n if (rule.type === \"function\") {\n rule.fn(value, query, data);\n return;\n }\n\n // 2. Predefined filter types\n const handler = this.getFilterHandler(rule.type);\n if (handler) {\n handler.call(this, query, rule.column, rule.columns, value, options);\n return;\n }\n\n // 3. Standard where operators\n this.applyWhereOperator(query, rule.type, rule.column, rule.columns, value, rule.key);\n }\n\n /**\n * Get filter handler for predefined types\n */\n private getFilterHandler(type: string): Function | undefined {\n const handlers: Record<string, Function> = {\n // Boolean filters\n bool: this.handleBoolean,\n boolean: this.handleBoolean,\n\n // Numeric filters\n int: this.handleInt,\n integer: this.handleInt,\n \"!int\": this.handleNotInt,\n \"int>\": (q: any, col: any, cols: any, val: any) =>\n this.handleIntComparison(q, col, cols, val, \">\"),\n \"int>=\": (q: any, col: any, cols: any, val: any) =>\n this.handleIntComparison(q, col, cols, val, \">=\"),\n \"int<\": (q: any, col: any, cols: any, val: any) =>\n this.handleIntComparison(q, col, cols, val, \"<\"),\n \"int<=\": (q: any, col: any, cols: any, val: any) =>\n this.handleIntComparison(q, col, cols, val, \"<=\"),\n inInt: this.handleInInt,\n number: this.handleNumber,\n inNumber: this.handleInNumber,\n float: this.handleFloat,\n double: this.handleFloat,\n inFloat: this.handleInNumber,\n\n // Null filters\n null: this.handleNull,\n notNull: this.handleNotNull,\n \"!null\": this.handleNotNull,\n\n // Date filters\n date: this.handleDate,\n \"date>\": (q: any, col: any, cols: any, val: any, opts: any) =>\n this.handleDateComparison(q, col, cols, val, opts, \">\"),\n \"date>=\": (q: any, col: any, cols: any, val: any, opts: any) =>\n this.handleDateComparison(q, col, cols, val, opts, \">=\"),\n \"date<\": (q: any, col: any, cols: any, val: any, opts: any) =>\n this.handleDateComparison(q, col, cols, val, opts, \"<\"),\n \"date<=\": (q: any, col: any, cols: any, val: any, opts: any) =>\n this.handleDateComparison(q, col, cols, val, opts, \"<=\"),\n dateBetween: this.handleDateBetween,\n inDate: this.handleInDate,\n\n // DateTime filters\n dateTime: this.handleDateTime,\n \"dateTime>\": (q: any, col: any, cols: any, val: any, opts: any) =>\n this.handleDateTimeComparison(q, col, cols, val, opts, \">\"),\n \"dateTime>=\": (q: any, col: any, cols: any, val: any, opts: any) =>\n this.handleDateTimeComparison(q, col, cols, val, opts, \">=\"),\n \"dateTime<\": (q: any, col: any, cols: any, val: any, opts: any) =>\n this.handleDateTimeComparison(q, col, cols, val, opts, \"<\"),\n \"dateTime<=\": (q: any, col: any, cols: any, val: any, opts: any) =>\n this.handleDateTimeComparison(q, col, cols, val, opts, \"<=\"),\n dateTimeBetween: this.handleDateTimeBetween,\n inDateTime: this.handleInDateTime,\n\n // Scope filter - applies local scope when value is truthy\n scope: this.handleScope,\n\n // With filter - eager-loads a relation when value is truthy\n with: this.handleWith,\n\n // JoinWith filter - eager-loads a relation via SQL JOIN when value is truthy\n joinWith: this.handleJoinWith,\n\n // Vector similarity search — calls similarTo(column, embedding[])\n similarTo: this.handleSimilarTo,\n };\n\n return handlers[type];\n }\n\n /**\n * Apply standard where operators\n */\n private applyWhereOperator(\n query: QueryBuilderContract,\n operator: string,\n column?: string,\n columns?: string[],\n value?: any,\n ruleName?: string,\n ): void {\n // Handle \"in\" prefix for array values\n if (operator.startsWith(\"in\") && operator !== \"int\" && !Array.isArray(value)) {\n value = [value];\n }\n\n // Single column\n if (column) {\n switch (operator) {\n case \"=\":\n query.where(column, value);\n break;\n case \"!=\":\n case \"<>\":\n query.where(column, \"!=\", value);\n break;\n case \">\":\n case \">=\":\n case \"<\":\n case \"<=\":\n query.where(column, operator, value);\n break;\n case \"in\":\n query.whereIn(column, Array.isArray(value) ? value : [value]);\n break;\n case \"not in\":\n query.whereNotIn(column, Array.isArray(value) ? value : [value]);\n break;\n case \"like\":\n query.whereLike(column, value);\n break;\n case \"not like\":\n query.whereNotLike(column, value);\n break;\n case \"between\":\n query.whereBetween(column, value);\n break;\n case \"not between\":\n query.whereNotBetween(column, value);\n break;\n }\n }\n // Multiple columns (OR condition)\n else if (columns) {\n if (operator === \"=\") {\n const conditions: any = {};\n for (const col of columns) {\n conditions[col] = value;\n }\n query.orWhere(conditions);\n } else if (operator === \"like\") {\n // (col0 LIKE value OR col1 LIKE value OR ...), OR'd with prior conditions —\n // the object form of orWhere() only ever emits \"=\", so \"like\" needs the\n // callback/group form to keep the operator instead of silently degrading\n // to equality (D1).\n query.orWhere((sub: QueryBuilderContract) => {\n columns.forEach((col, index) => {\n if (index === 0) {\n sub.where(col, \"like\", value);\n } else {\n sub.orWhere(col, \"like\", value);\n }\n });\n });\n } else {\n // Every other operator silently degraded to equality via the object form\n // of orWhere() — refuse instead of returning a correct-looking, wrong query.\n throw new Error(\n `Unsupported multi-column filter operator \"${operator}\" for rule \"${ruleName ?? columns.join(\",\")}\". ` +\n `Multi-column filters only support \"=\" and \"like\".`,\n );\n }\n }\n }\n\n // ============================================================================\n // BOOLEAN FILTERS\n // ============================================================================\n\n /**\n * Coerce a filter value to a boolean.\n *\n * Recognized truthy forms: `true`, `1`, `\"true\"`, `\"1\"`.\n * Recognized falsy forms: `false`, `0`, `\"false\"`, `\"0\"`.\n * Anything else falls back to `Boolean(value)`.\n *\n * NOTE: this intentionally does NOT treat \"non-empty\" as true — the previous\n * `|| !isEmpty(value)` fallback coerced `false`/`0` to `true`, inverting the\n * filter for explicitly-false values.\n */\n private coerceBoolean(value: any): boolean {\n if (value === true || value === 1 || value === \"true\" || value === \"1\") {\n return true;\n }\n\n if (value === false || value === 0 || value === \"false\" || value === \"0\") {\n return false;\n }\n\n return Boolean(value);\n }\n\n private handleBoolean(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n ) {\n const boolValue = this.coerceBoolean(value);\n if (column) {\n query.where(column, boolValue);\n } else if (columns) {\n const conditions: any = {};\n for (const col of columns) {\n conditions[col] = boolValue;\n }\n\n query.orWhere(conditions);\n }\n }\n\n // ============================================================================\n // NUMERIC FILTERS\n // ============================================================================\n private handleInt(query: QueryBuilderContract, column?: string, columns?: string[], value?: any) {\n const intValue = parseInt(value);\n if (column) {\n query.where(column, intValue);\n } else if (columns) {\n const conditions: any = {};\n for (const col of columns) {\n conditions[col] = intValue;\n }\n\n query.orWhere(conditions);\n }\n }\n\n private handleNotInt(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n ) {\n const intValue = parseInt(value);\n if (column) {\n query.where(column, \"!=\", intValue);\n } else if (columns) {\n // Use multiple orWhere calls for OR logic across columns\n for (const col of columns) {\n query.orWhere(col, \"!=\", intValue);\n }\n }\n }\n\n private handleIntComparison(\n query: QueryBuilderContract,\n column: any,\n columns: any,\n value: any,\n operator: string,\n ) {\n const intValue = parseInt(value);\n if (column) {\n query.where(column, operator, intValue);\n } else if (columns) {\n for (const col of columns) {\n query.orWhere(col, operator, intValue);\n }\n }\n }\n\n private handleInInt(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n ) {\n const values = (Array.isArray(value) ? value : [value]).map((v: any) => parseInt(v));\n if (column) {\n query.whereIn(column, values);\n } else if (columns) {\n // Use multiple orWhere calls with whereIn for each column\n for (const col of columns) {\n query.orWhere((q: any) => q.whereIn(col, values));\n }\n }\n }\n\n private handleNumber(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n ) {\n const numValue = Number(value);\n if (column) {\n query.where(column, numValue);\n } else if (columns) {\n const conditions: any = {};\n for (const col of columns) {\n conditions[col] = numValue;\n }\n\n query.orWhere(conditions);\n }\n }\n\n private handleInNumber(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n ) {\n const values = (Array.isArray(value) ? value : [value]).map((v: any) => Number(v));\n if (column) {\n query.whereIn(column, values);\n } else if (columns) {\n // Use multiple orWhere calls with whereIn for each column\n for (const col of columns) {\n query.orWhere((q: any) => q.whereIn(col, values));\n }\n }\n }\n\n private handleFloat(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n ) {\n const floatValue = parseFloat(value);\n if (column) {\n query.where(column, floatValue);\n } else if (columns) {\n const conditions: any = {};\n for (const col of columns) {\n conditions[col] = floatValue;\n }\n\n query.orWhere(conditions);\n }\n }\n\n // ============================================================================\n // NULL FILTERS\n // ============================================================================\n\n private handleNull(query: QueryBuilderContract, column?: string, columns?: string[]) {\n if (column) {\n query.whereNull(column);\n } else if (columns) {\n for (const col of columns) {\n query.orWhere({ [col]: null });\n }\n }\n }\n\n private handleNotNull(query: QueryBuilderContract, column?: string, columns?: string[]) {\n if (column) {\n query.whereNotNull(column);\n } else if (columns) {\n // Use whereNotNull for each column\n for (const col of columns) {\n query.orWhere((q: any) => q.whereNotNull(col));\n }\n }\n }\n\n // ============================================================================\n // SCOPE FILTER\n // ============================================================================\n\n /**\n * Handle scope filter - applies local scope and passes the filter value.\n *\n * Usage in filterBy:\n * ```typescript\n * filterBy: {\n * active: \"scope\", // Uses the filter key as scope name\n * isAdmin: [\"scope\", \"admin\"] // Uses custom scope name\n * }\n * ```\n *\n * When list({ active: true }) is called, it will call query.scope(\"active\", true)\n * When list({ status: \"pending\" }) is called, it will call query.scope(\"status\", \"pending\")\n */\n private handleScope(\n query: QueryBuilderContract,\n column?: string,\n _columns?: string[],\n value?: any,\n ) {\n // column holds the scope name (either the filter key or custom name from array format)\n if (column) {\n query.scope(column, value);\n }\n }\n\n // ============================================================================\n // WITH (EAGER LOAD) FILTER\n // ============================================================================\n\n /**\n * Handle with filter - eager-loads a relation when the filter value is truthy.\n *\n * Usage in filterBy:\n * ```typescript\n * filterBy: {\n * with_ai_model: [\"with\", \"ai_model\"], // load single relation\n * with_all: [\"with\", [\"ai_model\", \"unit\"]] // load multiple relations\n * }\n * ```\n *\n * When list({ with_ai_model: true }) is called, it will call query.with(\"ai_model\")\n */\n private handleWith(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n ) {\n if (!value) return;\n\n // Load a single named relation\n if (column) {\n if (query.with) {\n query.with(column);\n }\n return;\n }\n\n // Load multiple relations from the columns array\n if (columns) {\n for (const relation of columns) {\n if (query.with) {\n query.with(relation);\n }\n }\n }\n }\n\n /**\n * Handle joinWith filter - eager-loads a relation via SQL JOIN when the filter value is truthy.\n *\n * Usage in filterBy:\n * ```typescript\n * filterBy: {\n * with_ai_model: [\"joinWith\", \"ai_model\"], // load single relation via join\n * with_all: [\"joinWith\", [\"ai_model\", \"unit\"]] // load multiple relations via join\n * }\n * ```\n *\n * When list({ with_ai_model: true }) is called, it will call query.joinWith(\"ai_model\")\n */\n private handleJoinWith(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n ) {\n if (!value) return;\n\n if (!query.joinWith) {\n console.warn(\n \"[Repository] joinWith is not supported by the query builder. using with instead.\",\n );\n return this.handleWith(query, column, columns, value);\n }\n\n // Load a single named relation\n if (column) {\n query.joinWith(column);\n return;\n }\n\n // Load multiple relations from the columns array\n if (columns) {\n query.joinWith(...columns);\n }\n }\n\n // ============================================================================\n // VECTOR FILTER\n // ============================================================================\n\n /**\n * Handle similarTo filter — performs vector similarity search.\n *\n * The filter value must be a `number[]` (pre-computed embedding).\n * Delegates to `query.similarTo(column, embedding)` which is handled\n * driver-specifically (pgvector or MongoDB Atlas $vectorSearch).\n *\n * Usage in filterBy:\n * ```typescript\n * filterBy: {\n * organization_id: \"=\",\n * embedding: \"similarTo\",\n * }\n * ```\n *\n * Then in the service:\n * ```typescript\n * await vectorsRepository.list({ embedding: queryEmbedding, organization_id: orgId });\n * ```\n */\n private handleSimilarTo(\n query: QueryBuilderContract,\n column?: string,\n _columns?: string[],\n value?: any,\n ) {\n if (!column || !Array.isArray(value)) return;\n\n // Cast to any: Cascade's internal QueryBuilderContract still uses nearestTo;\n // our wrapper (CascadeQueryBuilder.similarTo) delegates to it correctly.\n (query as any).similarTo(column, value);\n }\n\n // ============================================================================\n // DATE FILTERS\n // ============================================================================\n\n private handleDate(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n options?: FilterOptions,\n ) {\n const dateValue = this.parseDate(value, options?.dateFormat);\n if (column) {\n query.whereDate(column, dateValue);\n } else if (columns) {\n for (const col of columns) {\n query.orWhere((q: any) => q.whereDate(col, dateValue));\n }\n }\n }\n\n private handleDateComparison(\n query: QueryBuilderContract,\n column: any,\n columns: any,\n value: any,\n options: any,\n operator: string,\n ) {\n const dateValue = this.parseDate(value, options?.dateFormat);\n if (column) {\n if (operator === \">\" || operator === \">=\") {\n query.whereDateAfter(column, dateValue);\n } else {\n query.whereDateBefore(column, dateValue);\n }\n } else if (columns) {\n for (const col of columns) {\n if (operator === \">\" || operator === \">=\") {\n query.orWhere((q: any) => q.whereDateAfter(col, dateValue));\n } else {\n query.orWhere((q: any) => q.whereDateBefore(col, dateValue));\n }\n }\n }\n }\n\n private handleDateBetween(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n options?: FilterOptions,\n ) {\n if (!Array.isArray(value) || value.length !== 2) return;\n const [start, end] = value.map((v: any) => this.parseDate(v, options?.dateFormat));\n if (column) {\n query.whereDateBetween(column, [start, end]);\n } else if (columns) {\n for (const col of columns) {\n query.orWhere((q: any) => q.whereDateBetween(col, [start, end]));\n }\n }\n }\n\n private handleInDate(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n options?: FilterOptions,\n ) {\n const dates = (Array.isArray(value) ? value : [value]).map((v: any) =>\n this.parseDate(v, options?.dateFormat),\n );\n if (column) {\n query.whereIn(column, dates);\n } else if (columns) {\n // Use multiple orWhere calls with whereIn for each column\n for (const col of columns) {\n query.orWhere((q: any) => q.whereIn(col, dates));\n }\n }\n }\n\n // ============================================================================\n // DATETIME FILTERS\n // ============================================================================\n\n private handleDateTime(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n options?: FilterOptions,\n ) {\n const dateValue = this.parseDateTime(value, options?.dateTimeFormat);\n if (column) {\n query.where(column, dateValue);\n } else if (columns) {\n const conditions: any = {};\n for (const col of columns) {\n conditions[col] = dateValue;\n }\n\n query.orWhere(conditions);\n }\n }\n\n private handleDateTimeComparison(\n query: QueryBuilderContract,\n column: any,\n columns: any,\n value: any,\n options: any,\n operator: string,\n ) {\n const dateValue = this.parseDateTime(value, options?.dateTimeFormat);\n if (column) {\n query.where(column, operator, dateValue);\n } else if (columns) {\n for (const col of columns) {\n query.orWhere(col, operator, dateValue);\n }\n }\n }\n\n private handleDateTimeBetween(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n options?: FilterOptions,\n ) {\n if (!Array.isArray(value) || value.length !== 2) return;\n const [start, end] = value.map((v: any) => this.parseDateTime(v, options?.dateTimeFormat));\n if (column) {\n query.whereBetween(column, [start, end]);\n } else if (columns) {\n for (const col of columns) {\n query.orWhere((q: any) => q.whereBetween(col, [start, end]));\n }\n }\n }\n\n private handleInDateTime(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n options?: FilterOptions,\n ) {\n const dates = (Array.isArray(value) ? value : [value]).map((v: any) =>\n this.parseDateTime(v, options?.dateTimeFormat),\n );\n if (column) {\n query.whereIn(column, dates);\n } else if (columns) {\n // Use multiple orWhere calls with whereIn for each column\n for (const col of columns) {\n query.orWhere((q: any) => q.whereIn(col, dates));\n }\n }\n }\n\n // ============================================================================\n // DATE PARSING UTILITIES\n // ============================================================================\n\n /**\n * Parse date string to Date object\n * TODO: Implement proper date parsing with format support\n */\n private parseDate(value: any, format?: string): Date {\n if (value instanceof Date) return value;\n return new Date(value);\n }\n\n /**\n * Parse datetime string to Date object\n * TODO: Implement proper datetime parsing with format support\n */\n private parseDateTime(value: any, format?: string): Date {\n if (value instanceof Date) return value;\n return new Date(value);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"filter-applicator.mjs","names":[],"sources":["../../../../../../../../../core/src/repositories/adapters/cascade/filter-applicator.ts"],"sourcesContent":["import type {\n QueryBuilderContract as CascadeQueryBuilder,\n QueryBuilderContract,\n} from \"@warlock.js/cascade\";\nimport type { FilterOptions, FilterRule, FilterRules } from \"../../contracts\";\n\n/**\n * Applies repository filters to a Cascade-Next query builder\n * Translates repository filter rules into Cascade query builder method calls\n */\nexport class FilterApplicator {\n /**\n * Apply filters to a Cascade query builder\n *\n * @param query - Cascade query builder instance\n * @param filters - Filter structure defining how to filter\n * @param data - Data containing filter values\n * @param options - Additional filter options (date formats, etc.)\n */\n public apply(\n query: CascadeQueryBuilder<any>,\n filters: FilterRules,\n data: any,\n options: FilterOptions,\n ): void {\n // `Object.entries` hands the rule over already narrowed; a `for...in` index\n // read is `FilterRule | undefined` under the strictness contract.\n for (const [key, filterRule] of Object.entries(filters)) {\n const value = data[key];\n\n if (value === undefined) continue;\n if (filterRule === undefined) continue;\n\n const rule = this.parseFilterRule(key, filterRule);\n this.applyFilterRule(query, rule, value, data, options);\n }\n }\n\n /**\n * Parse a filter rule into a structured format\n */\n private parseFilterRule(key: string, rule: FilterRule) {\n // Handle custom function\n if (typeof rule === \"function\") {\n return { type: \"function\", fn: rule, column: key, key };\n }\n\n // Handle array format: [\"operator\"] or [\"operator\", \"column\"] or [\"operator\", [\"col1\", \"col2\"]]\n if (Array.isArray(rule)) {\n const [operator, target] = rule;\n\n if (target === undefined) {\n return { type: operator, column: key, columns: undefined, key };\n }\n\n if (Array.isArray(target)) {\n return { type: operator, column: undefined, columns: target, key };\n }\n\n return { type: operator, column: target, columns: undefined, key };\n }\n\n // Handle simple operator string\n return { type: rule, column: key, columns: undefined, key };\n }\n\n /**\n * Apply a single filter rule to the query\n */\n private applyFilterRule(\n query: CascadeQueryBuilder<any>,\n rule: any,\n value: any,\n data: any,\n options: FilterOptions,\n ): void {\n // 1. Custom function filter\n if (rule.type === \"function\") {\n rule.fn(value, query, data);\n return;\n }\n\n // 2. Predefined filter types\n const handler = this.getFilterHandler(rule.type);\n if (handler) {\n handler.call(this, query, rule.column, rule.columns, value, options);\n return;\n }\n\n // 3. Standard where operators\n this.applyWhereOperator(query, rule.type, rule.column, rule.columns, value, rule.key);\n }\n\n /**\n * Get filter handler for predefined types\n */\n private getFilterHandler(type: string): Function | undefined {\n const handlers: Record<string, Function> = {\n // Boolean filters\n bool: this.handleBoolean,\n boolean: this.handleBoolean,\n\n // Numeric filters\n int: this.handleInt,\n integer: this.handleInt,\n \"!int\": this.handleNotInt,\n \"int>\": (q: any, col: any, cols: any, val: any) =>\n this.handleIntComparison(q, col, cols, val, \">\"),\n \"int>=\": (q: any, col: any, cols: any, val: any) =>\n this.handleIntComparison(q, col, cols, val, \">=\"),\n \"int<\": (q: any, col: any, cols: any, val: any) =>\n this.handleIntComparison(q, col, cols, val, \"<\"),\n \"int<=\": (q: any, col: any, cols: any, val: any) =>\n this.handleIntComparison(q, col, cols, val, \"<=\"),\n inInt: this.handleInInt,\n number: this.handleNumber,\n inNumber: this.handleInNumber,\n float: this.handleFloat,\n double: this.handleFloat,\n inFloat: this.handleInNumber,\n\n // Null filters\n null: this.handleNull,\n notNull: this.handleNotNull,\n \"!null\": this.handleNotNull,\n\n // Date filters\n date: this.handleDate,\n \"date>\": (q: any, col: any, cols: any, val: any, opts: any) =>\n this.handleDateComparison(q, col, cols, val, opts, \">\"),\n \"date>=\": (q: any, col: any, cols: any, val: any, opts: any) =>\n this.handleDateComparison(q, col, cols, val, opts, \">=\"),\n \"date<\": (q: any, col: any, cols: any, val: any, opts: any) =>\n this.handleDateComparison(q, col, cols, val, opts, \"<\"),\n \"date<=\": (q: any, col: any, cols: any, val: any, opts: any) =>\n this.handleDateComparison(q, col, cols, val, opts, \"<=\"),\n dateBetween: this.handleDateBetween,\n inDate: this.handleInDate,\n\n // DateTime filters\n dateTime: this.handleDateTime,\n \"dateTime>\": (q: any, col: any, cols: any, val: any, opts: any) =>\n this.handleDateTimeComparison(q, col, cols, val, opts, \">\"),\n \"dateTime>=\": (q: any, col: any, cols: any, val: any, opts: any) =>\n this.handleDateTimeComparison(q, col, cols, val, opts, \">=\"),\n \"dateTime<\": (q: any, col: any, cols: any, val: any, opts: any) =>\n this.handleDateTimeComparison(q, col, cols, val, opts, \"<\"),\n \"dateTime<=\": (q: any, col: any, cols: any, val: any, opts: any) =>\n this.handleDateTimeComparison(q, col, cols, val, opts, \"<=\"),\n dateTimeBetween: this.handleDateTimeBetween,\n inDateTime: this.handleInDateTime,\n\n // Scope filter - applies local scope when value is truthy\n scope: this.handleScope,\n\n // With filter - eager-loads a relation when value is truthy\n with: this.handleWith,\n\n // JoinWith filter - eager-loads a relation via SQL JOIN when value is truthy\n joinWith: this.handleJoinWith,\n\n // Vector similarity search — calls similarTo(column, embedding[])\n similarTo: this.handleSimilarTo,\n };\n\n return handlers[type];\n }\n\n /**\n * Apply standard where operators\n */\n private applyWhereOperator(\n query: QueryBuilderContract,\n operator: string,\n column?: string,\n columns?: string[],\n value?: any,\n ruleName?: string,\n ): void {\n // Handle \"in\" prefix for array values\n if (operator.startsWith(\"in\") && operator !== \"int\" && !Array.isArray(value)) {\n value = [value];\n }\n\n // Single column\n if (column) {\n switch (operator) {\n case \"=\":\n query.where(column, value);\n break;\n case \"!=\":\n case \"<>\":\n query.where(column, \"!=\", value);\n break;\n case \">\":\n case \">=\":\n case \"<\":\n case \"<=\":\n query.where(column, operator, value);\n break;\n case \"in\":\n query.whereIn(column, Array.isArray(value) ? value : [value]);\n break;\n case \"not in\":\n query.whereNotIn(column, Array.isArray(value) ? value : [value]);\n break;\n case \"like\":\n query.whereLike(column, value);\n break;\n case \"not like\":\n query.whereNotLike(column, value);\n break;\n case \"between\":\n query.whereBetween(column, value);\n break;\n case \"not between\":\n query.whereNotBetween(column, value);\n break;\n }\n }\n // Multiple columns (OR condition)\n else if (columns) {\n if (operator === \"=\") {\n const conditions: any = {};\n for (const col of columns) {\n conditions[col] = value;\n }\n query.orWhere(conditions);\n } else if (operator === \"like\") {\n // (col0 LIKE value OR col1 LIKE value OR ...), OR'd with prior conditions —\n // the object form of orWhere() only ever emits \"=\", so \"like\" needs the\n // callback/group form to keep the operator instead of silently degrading\n // to equality (D1).\n query.orWhere((sub: QueryBuilderContract) => {\n columns.forEach((col, index) => {\n if (index === 0) {\n sub.where(col, \"like\", value);\n } else {\n sub.orWhere(col, \"like\", value);\n }\n });\n });\n } else {\n // Every other operator silently degraded to equality via the object form\n // of orWhere() — refuse instead of returning a correct-looking, wrong query.\n throw new Error(\n `Unsupported multi-column filter operator \"${operator}\" for rule \"${ruleName ?? columns.join(\",\")}\". ` +\n `Multi-column filters only support \"=\" and \"like\".`,\n );\n }\n }\n }\n\n // ============================================================================\n // BOOLEAN FILTERS\n // ============================================================================\n\n /**\n * Coerce a filter value to a boolean.\n *\n * Recognized truthy forms: `true`, `1`, `\"true\"`, `\"1\"`.\n * Recognized falsy forms: `false`, `0`, `\"false\"`, `\"0\"`.\n * Anything else falls back to `Boolean(value)`.\n *\n * NOTE: this intentionally does NOT treat \"non-empty\" as true — the previous\n * `|| !isEmpty(value)` fallback coerced `false`/`0` to `true`, inverting the\n * filter for explicitly-false values.\n */\n private coerceBoolean(value: any): boolean {\n if (value === true || value === 1 || value === \"true\" || value === \"1\") {\n return true;\n }\n\n if (value === false || value === 0 || value === \"false\" || value === \"0\") {\n return false;\n }\n\n return Boolean(value);\n }\n\n private handleBoolean(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n ) {\n const boolValue = this.coerceBoolean(value);\n if (column) {\n query.where(column, boolValue);\n } else if (columns) {\n const conditions: any = {};\n for (const col of columns) {\n conditions[col] = boolValue;\n }\n\n query.orWhere(conditions);\n }\n }\n\n // ============================================================================\n // NUMERIC FILTERS\n // ============================================================================\n private handleInt(query: QueryBuilderContract, column?: string, columns?: string[], value?: any) {\n const intValue = parseInt(value);\n if (column) {\n query.where(column, intValue);\n } else if (columns) {\n const conditions: any = {};\n for (const col of columns) {\n conditions[col] = intValue;\n }\n\n query.orWhere(conditions);\n }\n }\n\n private handleNotInt(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n ) {\n const intValue = parseInt(value);\n if (column) {\n query.where(column, \"!=\", intValue);\n } else if (columns) {\n // Use multiple orWhere calls for OR logic across columns\n for (const col of columns) {\n query.orWhere(col, \"!=\", intValue);\n }\n }\n }\n\n private handleIntComparison(\n query: QueryBuilderContract,\n column: any,\n columns: any,\n value: any,\n operator: string,\n ) {\n const intValue = parseInt(value);\n if (column) {\n query.where(column, operator, intValue);\n } else if (columns) {\n for (const col of columns) {\n query.orWhere(col, operator, intValue);\n }\n }\n }\n\n private handleInInt(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n ) {\n const values = (Array.isArray(value) ? value : [value]).map((v: any) => parseInt(v));\n if (column) {\n query.whereIn(column, values);\n } else if (columns) {\n // Use multiple orWhere calls with whereIn for each column\n for (const col of columns) {\n query.orWhere((q: any) => q.whereIn(col, values));\n }\n }\n }\n\n private handleNumber(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n ) {\n const numValue = Number(value);\n if (column) {\n query.where(column, numValue);\n } else if (columns) {\n const conditions: any = {};\n for (const col of columns) {\n conditions[col] = numValue;\n }\n\n query.orWhere(conditions);\n }\n }\n\n private handleInNumber(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n ) {\n const values = (Array.isArray(value) ? value : [value]).map((v: any) => Number(v));\n if (column) {\n query.whereIn(column, values);\n } else if (columns) {\n // Use multiple orWhere calls with whereIn for each column\n for (const col of columns) {\n query.orWhere((q: any) => q.whereIn(col, values));\n }\n }\n }\n\n private handleFloat(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n ) {\n const floatValue = parseFloat(value);\n if (column) {\n query.where(column, floatValue);\n } else if (columns) {\n const conditions: any = {};\n for (const col of columns) {\n conditions[col] = floatValue;\n }\n\n query.orWhere(conditions);\n }\n }\n\n // ============================================================================\n // NULL FILTERS\n // ============================================================================\n\n private handleNull(query: QueryBuilderContract, column?: string, columns?: string[]) {\n if (column) {\n query.whereNull(column);\n } else if (columns) {\n for (const col of columns) {\n query.orWhere({ [col]: null });\n }\n }\n }\n\n private handleNotNull(query: QueryBuilderContract, column?: string, columns?: string[]) {\n if (column) {\n query.whereNotNull(column);\n } else if (columns) {\n // Use whereNotNull for each column\n for (const col of columns) {\n query.orWhere((q: any) => q.whereNotNull(col));\n }\n }\n }\n\n // ============================================================================\n // SCOPE FILTER\n // ============================================================================\n\n /**\n * Handle scope filter - applies local scope and passes the filter value.\n *\n * Usage in filterBy:\n * ```typescript\n * filterBy: {\n * active: \"scope\", // Uses the filter key as scope name\n * isAdmin: [\"scope\", \"admin\"] // Uses custom scope name\n * }\n * ```\n *\n * When list({ active: true }) is called, it will call query.scope(\"active\", true)\n * When list({ status: \"pending\" }) is called, it will call query.scope(\"status\", \"pending\")\n */\n private handleScope(\n query: QueryBuilderContract,\n column?: string,\n _columns?: string[],\n value?: any,\n ) {\n // column holds the scope name (either the filter key or custom name from array format)\n if (column) {\n query.scope(column, value);\n }\n }\n\n // ============================================================================\n // WITH (EAGER LOAD) FILTER\n // ============================================================================\n\n /**\n * Handle with filter - eager-loads a relation when the filter value is truthy.\n *\n * Usage in filterBy:\n * ```typescript\n * filterBy: {\n * with_ai_model: [\"with\", \"ai_model\"], // load single relation\n * with_all: [\"with\", [\"ai_model\", \"unit\"]] // load multiple relations\n * }\n * ```\n *\n * When list({ with_ai_model: true }) is called, it will call query.with(\"ai_model\")\n */\n private handleWith(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n ) {\n if (!value) return;\n\n // Load a single named relation\n if (column) {\n if (query.with) {\n query.with(column);\n }\n return;\n }\n\n // Load multiple relations from the columns array\n if (columns) {\n for (const relation of columns) {\n if (query.with) {\n query.with(relation);\n }\n }\n }\n }\n\n /**\n * Handle joinWith filter - eager-loads a relation via SQL JOIN when the filter value is truthy.\n *\n * Usage in filterBy:\n * ```typescript\n * filterBy: {\n * with_ai_model: [\"joinWith\", \"ai_model\"], // load single relation via join\n * with_all: [\"joinWith\", [\"ai_model\", \"unit\"]] // load multiple relations via join\n * }\n * ```\n *\n * When list({ with_ai_model: true }) is called, it will call query.joinWith(\"ai_model\")\n */\n private handleJoinWith(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n ) {\n if (!value) return;\n\n if (!query.joinWith) {\n console.warn(\n \"[Repository] joinWith is not supported by the query builder. using with instead.\",\n );\n return this.handleWith(query, column, columns, value);\n }\n\n // Load a single named relation\n if (column) {\n query.joinWith(column);\n return;\n }\n\n // Load multiple relations from the columns array\n if (columns) {\n query.joinWith(...columns);\n }\n }\n\n // ============================================================================\n // VECTOR FILTER\n // ============================================================================\n\n /**\n * Handle similarTo filter — performs vector similarity search.\n *\n * The filter value must be a `number[]` (pre-computed embedding).\n * Delegates to `query.similarTo(column, embedding)` which is handled\n * driver-specifically (pgvector or MongoDB Atlas $vectorSearch).\n *\n * Usage in filterBy:\n * ```typescript\n * filterBy: {\n * organization_id: \"=\",\n * embedding: \"similarTo\",\n * }\n * ```\n *\n * Then in the service:\n * ```typescript\n * await vectorsRepository.list({ embedding: queryEmbedding, organization_id: orgId });\n * ```\n */\n private handleSimilarTo(\n query: QueryBuilderContract,\n column?: string,\n _columns?: string[],\n value?: any,\n ) {\n if (!column || !Array.isArray(value)) return;\n\n // Cast to any: Cascade's internal QueryBuilderContract still uses nearestTo;\n // our wrapper (CascadeQueryBuilder.similarTo) delegates to it correctly.\n (query as any).similarTo(column, value);\n }\n\n // ============================================================================\n // DATE FILTERS\n // ============================================================================\n\n private handleDate(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n options?: FilterOptions,\n ) {\n const dateValue = this.parseDate(value, options?.dateFormat);\n if (column) {\n query.whereDate(column, dateValue);\n } else if (columns) {\n for (const col of columns) {\n query.orWhere((q: any) => q.whereDate(col, dateValue));\n }\n }\n }\n\n private handleDateComparison(\n query: QueryBuilderContract,\n column: any,\n columns: any,\n value: any,\n options: any,\n operator: string,\n ) {\n const dateValue = this.parseDate(value, options?.dateFormat);\n if (column) {\n if (operator === \">\" || operator === \">=\") {\n query.whereDateAfter(column, dateValue);\n } else {\n query.whereDateBefore(column, dateValue);\n }\n } else if (columns) {\n for (const col of columns) {\n if (operator === \">\" || operator === \">=\") {\n query.orWhere((q: any) => q.whereDateAfter(col, dateValue));\n } else {\n query.orWhere((q: any) => q.whereDateBefore(col, dateValue));\n }\n }\n }\n }\n\n private handleDateBetween(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n options?: FilterOptions,\n ) {\n if (!Array.isArray(value) || value.length !== 2) return;\n const [start, end] = value.map((v: any) => this.parseDate(v, options?.dateFormat));\n\n // `value.length === 2` is checked above, so both exist — but the compiler\n // does not narrow destructured elements from a length test. Returning\n // rather than defaulting: this builds a date RANGE for a query, and a\n // half-formed range would silently filter on a boundary the caller never\n // asked for.\n if (start === undefined || end === undefined) return;\n\n if (column) {\n query.whereDateBetween(column, [start, end]);\n } else if (columns) {\n for (const col of columns) {\n query.orWhere((q: any) => q.whereDateBetween(col, [start, end]));\n }\n }\n }\n\n private handleInDate(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n options?: FilterOptions,\n ) {\n const dates = (Array.isArray(value) ? value : [value]).map((v: any) =>\n this.parseDate(v, options?.dateFormat),\n );\n if (column) {\n query.whereIn(column, dates);\n } else if (columns) {\n // Use multiple orWhere calls with whereIn for each column\n for (const col of columns) {\n query.orWhere((q: any) => q.whereIn(col, dates));\n }\n }\n }\n\n // ============================================================================\n // DATETIME FILTERS\n // ============================================================================\n\n private handleDateTime(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n options?: FilterOptions,\n ) {\n const dateValue = this.parseDateTime(value, options?.dateTimeFormat);\n if (column) {\n query.where(column, dateValue);\n } else if (columns) {\n const conditions: any = {};\n for (const col of columns) {\n conditions[col] = dateValue;\n }\n\n query.orWhere(conditions);\n }\n }\n\n private handleDateTimeComparison(\n query: QueryBuilderContract,\n column: any,\n columns: any,\n value: any,\n options: any,\n operator: string,\n ) {\n const dateValue = this.parseDateTime(value, options?.dateTimeFormat);\n if (column) {\n query.where(column, operator, dateValue);\n } else if (columns) {\n for (const col of columns) {\n query.orWhere(col, operator, dateValue);\n }\n }\n }\n\n private handleDateTimeBetween(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n options?: FilterOptions,\n ) {\n if (!Array.isArray(value) || value.length !== 2) return;\n const [start, end] = value.map((v: any) => this.parseDateTime(v, options?.dateTimeFormat));\n if (column) {\n query.whereBetween(column, [start, end]);\n } else if (columns) {\n for (const col of columns) {\n query.orWhere((q: any) => q.whereBetween(col, [start, end]));\n }\n }\n }\n\n private handleInDateTime(\n query: QueryBuilderContract,\n column?: string,\n columns?: string[],\n value?: any,\n options?: FilterOptions,\n ) {\n const dates = (Array.isArray(value) ? value : [value]).map((v: any) =>\n this.parseDateTime(v, options?.dateTimeFormat),\n );\n if (column) {\n query.whereIn(column, dates);\n } else if (columns) {\n // Use multiple orWhere calls with whereIn for each column\n for (const col of columns) {\n query.orWhere((q: any) => q.whereIn(col, dates));\n }\n }\n }\n\n // ============================================================================\n // DATE PARSING UTILITIES\n // ============================================================================\n\n /**\n * Parse date string to Date object\n * TODO: Implement proper date parsing with format support\n */\n private parseDate(value: any, format?: string): Date {\n if (value instanceof Date) return value;\n return new Date(value);\n }\n\n /**\n * Parse datetime string to Date object\n * TODO: Implement proper datetime parsing with format support\n */\n private parseDateTime(value: any, format?: string): Date {\n if (value instanceof Date) return value;\n return new Date(value);\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"query-builder.contract.d.mts","names":[],"sources":["../../../../../../../../core/src/repositories/contracts/query-builder.contract.ts"],"mappings":";;;;;AAgBA;;;;KAAY,aAAA,uBAAoC,MAAA,oBAA0B,KAAA,CAAM,MAAA;;;;;;;;AAAM;KAU1E,wBAAA,YAAoC,MAAM;;;;AAAA;AAQtD;;KAAY,oBAAA,GAAuB,MAAM,SAAS,wBAAA;;AAAwB;AAQ1E;;;;UAAiB,oBAAA;EAqEkB;;;;;;;;;;EAtDjC,KAAA,CAAM,KAAA,UAAe,KAAA;EAsSD;;;;;;;;;;;EAzRpB,KAAA,CAAM,KAAA,UAAe,QAAA,EAAU,aAAA,EAAe,KAAA;EAoVkB;;;;;;;;;EAzUhE,KAAA,CAAM,UAAA,EAAY,MAAA;EA8VsC;;;;;;;;;EAnVxD,KAAA,CAAM,QAAA,GAAW,KAAA;EAtB6B;;;;;;;EA+B9C,OAAA,CAAQ,KAAA,UAAe,KAAA;EAAf;;;;;;;;EAUR,OAAA,CAAQ,KAAA,UAAe,QAAA,EAAU,aAAA,EAAe,KAAA;EAQxC;;;;;;EAAR,OAAA,CAAQ,UAAA,EAAY,MAAA;EA6BpB;;;;;;;;;;EAjBA,OAAA,CAAQ,KAAA,UAAe,MAAA;EAqEvB;;;;;;;EA5DA,UAAA,CAAW,KAAA,UAAe,MAAA;EAuG1B;;;;;;EA/FA,SAAA,CAAU,KAAA;EAkHH;;;;;;EA1GP,YAAA,CAAa,KAAA;EAoJb;;;;;;;;;;EAxIA,YAAA,CAAa,KAAA,UAAe,KAAA;EA0JX;;;;;;;;;;EA9IjB,SAAA,CAAU,KAAA,UAAe,OAAA;EAmLL;;;EA9KpB,MAAA;EAsMA;;;;;;;;;EAvLA,MAAA,CAAO,MAAA;EAyMG;;;;;;;;;EA9LV,MAAA,IAAU,MAAA;EAuMqC;;;;;;EA/L/C,QAAA,CAAS,MAAA;EA2MwE;;;;;;EAnMjF,QAAA,IAAY,MAAA;EA2NZ;;;;;;;;;;EA3MA,OAAA,CAAQ,KAAA,UAAe,SAAA;;;;;;;;;;EAWvB,MAAA,CAAO,OAAA,EAAS,MAAA;;;;;;;EAQhB,MAAA,CAAO,KAAA;;;;;;;EAYP,KAAA,CAAM,KAAA;;;;;;;EAQN,MAAA,CAAO,MAAA;;;;;;;EAQP,IAAA,CAAK,KAAA;;;;;;;;;EAcL,YAAA,CAAa,OAAA,EAAS,WAAA,QAAmB,IAAA,OAAW,OAAA,EAAS,aAAA;;;;;;EAW7D,GAAA,IAAO,OAAA,CAAQ,CAAA;;;;;;EAOf,KAAA,IAAS,OAAA,CAAQ,CAAA;;;;;;EAOjB,KAAA,IAAS,OAAA;;;;;;;;;;EAWT,GAAA,CAAI,KAAA,WAAgB,OAAA;;;;;;;;;;EAWpB,GAAA,CAAI,KAAA,WAAgB,OAAA;;;;;;;EAQpB,GAAA,CAAI,KAAA,WAAgB,OAAA;;;;;;;EAQpB,GAAA,CAAI,KAAA,WAAgB,OAAA;;;;;;;;;;;;;;;EAgBpB,OAAA,KAAY,MAAA,mBACV,MAAA,EAAQ,aAAA,EACR,UAAA,EAAY,oBAAA,GACX,OAAA,CAAQ,CAAA;;;;;;;;;;;;;;EAeX,SAAA,KAAc,MAAA,mBAAyB,UAAA,EAAY,oBAAA,GAAuB,OAAA,CAAQ,CAAA;;;;;;;;EASlF,QAAA,CAAS,IAAA,UAAc,KAAA,WAAgB,OAAA,CAAQ,gBAAA,CAAiB,CAAA;;;;;;;;;;;EAYhE,cAAA,CAAe,OAAA,EAAS,uBAAA,GAA0B,OAAA,CAAQ,sBAAA,CAAuB,CAAA;;;;;;;;EASjF,KAAA,CAAM,IAAA,UAAc,QAAA,EAAU,aAAA,CAAc,CAAA,IAAK,OAAA;;;;;;;;;;EAejD,IAAA,EAAM,QAAA;;;;;;;;;;EAWN,QAAA,KAAa,SAAA;;;;;;EAOb,KAAA;;;;;;;;;;;;;;;;;;;;;EAsBA,SAAA,CAAU,MAAA,UAAgB,SAAA,YAAqB,KAAA;AAAA"}
1
+ {"version":3,"file":"query-builder.contract.d.mts","names":[],"sources":["../../../../../../../../core/src/repositories/contracts/query-builder.contract.ts"],"mappings":";;;;;AAgBA;;;;KAAY,aAAA,uBACU,MAAA,oBAA0B,KAAA,CAAM,MAAA;;;;;;;;AAAM;KAUhD,wBAAA,YAAoC,MAAM;;;;AAAA;AAQtD;;KAAY,oBAAA,GAAuB,MAAM,SAAS,wBAAA;;AAAwB;AAQ1E;;;;UAAiB,oBAAA;EAqEkB;;;;;;;;;;EAtDjC,KAAA,CAAM,KAAA,UAAe,KAAA;EAsSD;;;;;;;;;;;EAzRpB,KAAA,CAAM,KAAA,UAAe,QAAA,EAAU,aAAA,EAAe,KAAA;EAoVkB;;;;;;;;;EAzUhE,KAAA,CAAM,UAAA,EAAY,MAAA;EA8VsC;;;;;;;;;EAnVxD,KAAA,CAAM,QAAA,GAAW,KAAA;EAtB6B;;;;;;;EA+B9C,OAAA,CAAQ,KAAA,UAAe,KAAA;EAAf;;;;;;;;EAUR,OAAA,CAAQ,KAAA,UAAe,QAAA,EAAU,aAAA,EAAe,KAAA;EAQxC;;;;;;EAAR,OAAA,CAAQ,UAAA,EAAY,MAAA;EA6BpB;;;;;;;;;;EAjBA,OAAA,CAAQ,KAAA,UAAe,MAAA;EAqEvB;;;;;;;EA5DA,UAAA,CAAW,KAAA,UAAe,MAAA;EAuG1B;;;;;;EA/FA,SAAA,CAAU,KAAA;EAkHH;;;;;;EA1GP,YAAA,CAAa,KAAA;EAoJb;;;;;;;;;;EAxIA,YAAA,CAAa,KAAA,UAAe,KAAA;EA0JX;;;;;;;;;;EA9IjB,SAAA,CAAU,KAAA,UAAe,OAAA;EAmLL;;;EA9KpB,MAAA;EAsMA;;;;;;;;;EAvLA,MAAA,CAAO,MAAA;EAyMG;;;;;;;;;EA9LV,MAAA,IAAU,MAAA;EAuMqC;;;;;;EA/L/C,QAAA,CAAS,MAAA;EA2MwE;;;;;;EAnMjF,QAAA,IAAY,MAAA;EA2NZ;;;;;;;;;;EA3MA,OAAA,CAAQ,KAAA,UAAe,SAAA;;;;;;;;;;EAWvB,MAAA,CAAO,OAAA,EAAS,MAAA;;;;;;;EAQhB,MAAA,CAAO,KAAA;;;;;;;EAYP,KAAA,CAAM,KAAA;;;;;;;EAQN,MAAA,CAAO,MAAA;;;;;;;EAQP,IAAA,CAAK,KAAA;;;;;;;;;EAcL,YAAA,CAAa,OAAA,EAAS,WAAA,QAAmB,IAAA,OAAW,OAAA,EAAS,aAAA;;;;;;EAW7D,GAAA,IAAO,OAAA,CAAQ,CAAA;;;;;;EAOf,KAAA,IAAS,OAAA,CAAQ,CAAA;;;;;;EAOjB,KAAA,IAAS,OAAA;;;;;;;;;;EAWT,GAAA,CAAI,KAAA,WAAgB,OAAA;;;;;;;;;;EAWpB,GAAA,CAAI,KAAA,WAAgB,OAAA;;;;;;;EAQpB,GAAA,CAAI,KAAA,WAAgB,OAAA;;;;;;;EAQpB,GAAA,CAAI,KAAA,WAAgB,OAAA;;;;;;;;;;;;;;;EAgBpB,OAAA,KAAY,MAAA,mBACV,MAAA,EAAQ,aAAA,EACR,UAAA,EAAY,oBAAA,GACX,OAAA,CAAQ,CAAA;;;;;;;;;;;;;;EAeX,SAAA,KAAc,MAAA,mBAAyB,UAAA,EAAY,oBAAA,GAAuB,OAAA,CAAQ,CAAA;;;;;;;;EASlF,QAAA,CAAS,IAAA,UAAc,KAAA,WAAgB,OAAA,CAAQ,gBAAA,CAAiB,CAAA;;;;;;;;;;;EAYhE,cAAA,CAAe,OAAA,EAAS,uBAAA,GAA0B,OAAA,CAAQ,sBAAA,CAAuB,CAAA;;;;;;;;EASjF,KAAA,CAAM,IAAA,UAAc,QAAA,EAAU,aAAA,CAAc,CAAA,IAAK,OAAA;;;;;;;;;;EAejD,IAAA,EAAM,QAAA;;;;;;;;;;EAWN,QAAA,KAAa,SAAA;;;;;;EAOb,KAAA;;;;;;;;;;;;;;;;;;;;;EAsBA,SAAA,CAAU,MAAA,UAAgB,SAAA,YAAqB,KAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.mts","names":[],"sources":["../../../../../../../../core/src/repositories/contracts/types.ts"],"mappings":"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"}
1
+ {"version":3,"file":"types.d.mts","names":[],"sources":["../../../../../../../../core/src/repositories/contracts/types.ts"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"resource-field-builder.d.mts","names":[],"sources":["../../../../../../../core/src/resource/resource-field-builder.ts"],"mappings":";;;;cAaa,oBAAA;EAAA,mBAwD2B,IAAA,EAAM,2BAAA;EAxDjC;;;EAAA,UAID,UAAA;EAuCkB;;;;EAAA,UAjClB,UAAA;EAmS0B;;;;EAAA,UA7R1B,YAAA;EAZA;;;EAAA,UAiBA,YAAA;EAKA;;;EAAA,UAAA,UAAA;EAiBkB;;;EAAA,UAZlB,aAAA;EAkCI;;;EAAA,UA7BJ,SAAA;EAsDS;;;;;EAAA,UA/CT,gBAAA,EAAkB,qCAAA;EAwFrB;;;cA3E+B,IAAA,EAAM,2BAAA;EA8FrC;;;;;EAAA,OArFO,YAAA,CAAa,QAAA,WAAmB,oBAAA;EAgHpC;;;;EAvFH,WAAA,CAAY,GAAA;EA2IK;;;EAlIjB,IAAA,CAAK,SAAA;EA0MiB;;;EAlMtB,QAAA;;;;;EASA,KAAA;;;;EAQA,WAAA;;;;EAOA,OAAA,CAAQ,KAAA;;;;EASR,MAAA,CAAO,MAAA;;;;;EAUP,WAAA,CAAY,OAAA,EAAS,qCAAA;;;;;EAUrB,SAAA,CAAU,KAAA,OAAY,MAAA;;;;YAiBnB,oBAAA,CAAqB,KAAA,OAAY,MAAA;;;;YAoDjC,aAAA,CAAc,KAAA,WAAgB,IAAA,EAAM,MAAA;;;;YAwEpC,kBAAA,CAAmB,KAAA,EAAO,eAAA,aAA4B,MAAA;AAAA"}
1
+ {"version":3,"file":"resource-field-builder.d.mts","names":[],"sources":["../../../../../../../core/src/resource/resource-field-builder.ts"],"mappings":";;;;cAgBa,oBAAA;EAAA,mBAwD2B,IAAA,EAAM,2BAAA;EAxDjC;;;EAAA,UAID,UAAA;EAuCkB;;;;EAAA,UAjClB,UAAA;EAmS0B;;;;EAAA,UA7R1B,YAAA;EAZA;;;EAAA,UAiBA,YAAA;EAKA;;;EAAA,UAAA,UAAA;EAiBkB;;;EAAA,UAZlB,aAAA;EAkCI;;;EAAA,UA7BJ,SAAA;EAsDS;;;;;EAAA,UA/CT,gBAAA,EAAkB,qCAAA;EAwFrB;;;cA3E+B,IAAA,EAAM,2BAAA;EA8FrC;;;;;EAAA,OArFO,YAAA,CAAa,QAAA,WAAmB,oBAAA;EAgHpC;;;;EAvFH,WAAA,CAAY,GAAA;EA2IK;;;EAlIjB,IAAA,CAAK,SAAA;EA0MiB;;;EAlMtB,QAAA;;;;;EASA,KAAA;;;;EAQA,WAAA;;;;EAOA,OAAA,CAAQ,KAAA;;;;EASR,MAAA,CAAO,MAAA;;;;;EAUP,WAAA,CAAY,OAAA,EAAS,qCAAA;;;;;EAUrB,SAAA,CAAU,KAAA,OAAY,MAAA;;;;YAiBnB,oBAAA,CAAqB,KAAA,OAAY,MAAA;;;;YAoDjC,aAAA,CAAc,KAAA,WAAgB,IAAA,EAAM,MAAA;;;;YAwEpC,kBAAA,CAAmB,KAAA,EAAO,eAAA,aAA4B,MAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"resource-field-builder.mjs","names":[],"sources":["../../../../../../../core/src/resource/resource-field-builder.ts"],"sourcesContent":["import { isObject } from \"@mongez/supportive-is\";\nimport dayjs from \"dayjs\";\nimport relativeTime from \"dayjs/plugin/relativeTime.js\";\nimport { storage } from \"../storage\";\n\n// `humanTime` date options call dayjs(...).fromNow(), which lives in the\n// relativeTime plugin. dayjs.extend is idempotent (a plugin registers itself\n// once), so extending here at module load is safe to repeat.\ndayjs.extend(relativeTime);\nimport { uploadsUrl, url } from \"../utils/urls\";\nimport { type LocalizedObject } from \"./../utils/get-localized\";\nimport { type ResourceFieldBuilderDateOutputOptions, type ResourceOutputValueCastType } from \"./types\";\n\nexport class ResourceFieldBuilder {\n /**\n * Field value\n */\n protected fieldValue?: unknown;\n\n /**\n * Whether the value is nullable\n * If set to false and value is null, it will be returned as undefined\n */\n protected isNullable = false;\n\n /**\n * Whether this field is an array\n * When true, transform() maps over each element using the base type\n */\n protected isArrayField = false;\n\n /**\n * Default value\n */\n protected defaultValue?: unknown;\n\n /**\n * Date format\n */\n protected dateFormat = \"DD-MM-YYYY hh:mm:ss A\";\n\n /**\n * Input key\n */\n protected inputKeyToUse?: string;\n\n /**\n * Add a condition before transforming the value\n */\n protected condition?: () => boolean;\n\n /**\n * Define how date fields are returned\n * If type of the date options is string then it will be returned as a string\n * otherwise it will be returned as an object contains the date options\n */\n protected dateOptionsInput: ResourceFieldBuilderDateOutputOptions = {\n format: true,\n timestamp: true,\n timezone: false,\n locale: false,\n offset: false,\n humanTime: true,\n iso: true,\n };\n\n /**\n * Constructor\n */\n public constructor(protected readonly type: ResourceOutputValueCastType) {\n //\n }\n\n /**\n * Parse a cast type string (including suffixes) into a configured builder.\n * Suffix order: [] before ? (e.g. \"string[]?\")\n * Parsing strips right-to-left: ? first, then [].\n */\n public static fromCastType(castType: string): ResourceFieldBuilder {\n let baseType = castType;\n let nullable = false;\n let isArray = false;\n\n if (baseType.endsWith(\"?\")) {\n nullable = true;\n baseType = baseType.slice(0, -1);\n }\n\n if (baseType.endsWith(\"[]\")) {\n isArray = true;\n baseType = baseType.slice(0, -2);\n }\n\n const builder = new ResourceFieldBuilder(baseType as ResourceOutputValueCastType);\n if (nullable) builder.nullable();\n if (isArray) builder.array();\n return builder;\n }\n\n /**\n * Set input key\n * Will be used in transformation if provided\n */\n public setInputKey(key: string) {\n this.inputKeyToUse = key;\n\n return this;\n }\n\n /**\n * Add a condition before transforming the value\n */\n public when(condition: () => boolean) {\n this.condition = condition;\n return this;\n }\n\n /**\n * Set whether the value is nullable\n */\n public nullable() {\n this.isNullable = true;\n return this;\n }\n\n /**\n * Mark this field as an array\n * transform() will map over each element using the base type\n */\n public array() {\n this.isArrayField = true;\n return this;\n }\n\n /**\n * Get input key\n */\n public getInputKey() {\n return this.inputKeyToUse;\n }\n\n /**\n * Set default value\n */\n public default(value: unknown) {\n this.defaultValue = value;\n\n return this;\n }\n\n /**\n * Set field format\n */\n public format(format: string) {\n this.dateFormat = format;\n\n return this;\n }\n\n /**\n * Set date options\n * This will override current date options\n */\n public dateOptions(options: ResourceFieldBuilderDateOutputOptions) {\n this.dateOptionsInput = options;\n\n return this;\n }\n\n /**\n * Transform the value.\n * When isArrayField is true, maps over each element using transformSingleValue.\n */\n public transform(value: any, locale?: string) {\n if (this.isArrayField) {\n if (!Array.isArray(value)) {\n return this.isNullable ? null : [];\n }\n\n return value\n .map((item) => this.transformSingleValue(item, locale))\n .filter((v) => v !== undefined);\n }\n\n return this.transformSingleValue(value, locale);\n }\n\n /**\n * Transform a single value according to the base type.\n */\n protected transformSingleValue(value: any, locale?: string) {\n if (value === undefined || value === null) {\n return this.isNullable ? null : this.defaultValue;\n }\n\n if (this.condition && !this.condition()) {\n return this.isNullable ? null : this.defaultValue;\n }\n\n switch (this.type) {\n case \"string\":\n return String(value);\n case \"number\": {\n const num = Number(value);\n return isNaN(num) ? (this.isNullable ? null : undefined) : num;\n }\n case \"boolean\":\n return Boolean(value);\n case \"float\": {\n const float = parseFloat(value);\n return isNaN(float) ? (this.isNullable ? null : undefined) : float;\n }\n\n case \"int\": {\n const int = parseInt(value);\n return isNaN(int) ? (this.isNullable ? null : undefined) : int;\n }\n\n case \"date\":\n return this.transformDate(value as string | Date, locale);\n case \"localized\":\n return this.transformLocalized(value as LocalizedObject[], locale);\n case \"url\":\n return url(value as string);\n case \"uploadsUrl\":\n return uploadsUrl(value as string);\n case \"storageUrl\":\n return storage.url(value as string);\n case \"object\":\n return isObject(value) && !Array.isArray(value) && Object.keys(value).length > 0\n ? value\n : this.isNullable\n ? null\n : undefined;\n case \"array\":\n return Array.isArray(value) ? value : this.isNullable ? null : undefined;\n }\n }\n\n /**\n * Transform date value\n */\n protected transformDate(value: string | Date, locale?: string) {\n if (typeof this.dateOptionsInput === \"string\") {\n if (this.dateOptionsInput === \"format\") {\n return dayjs(value).format(this.dateFormat);\n }\n\n if (this.dateOptionsInput === \"iso\") {\n return dayjs(value).toISOString();\n }\n\n if (this.dateOptionsInput === \"timestamp\") {\n return dayjs(value).valueOf();\n }\n\n if (this.dateOptionsInput === \"humanTime\") {\n return (dayjs as any)(value).fromNow();\n }\n\n if (this.dateOptionsInput === \"locale\") {\n if (!locale) {\n return dayjs(value).format(this.dateFormat);\n }\n\n return dayjs(value).locale(locale).format(this.dateFormat);\n }\n }\n\n // now manage it as an object based on date options what's marked as true\n const output: {\n format?: string;\n timestamp?: number;\n humanTime?: string;\n locale?: string;\n iso?: string;\n } = {};\n\n let dayjsObject = dayjs((value as any)?.iso || value);\n\n if (locale) {\n dayjsObject = dayjsObject.locale(locale);\n }\n\n if (this.dateOptionsInput.iso) {\n output.iso = dayjsObject.toISOString();\n }\n\n if (this.dateOptionsInput.format) {\n output.format = dayjsObject.format(this.dateFormat);\n }\n\n if (this.dateOptionsInput.timestamp) {\n output.timestamp = dayjsObject.valueOf();\n }\n\n if (this.dateOptionsInput.humanTime) {\n output.humanTime = (dayjsObject as any).fromNow();\n }\n\n if (this.dateOptionsInput.locale) {\n output.locale = dayjsObject.format(this.dateFormat);\n }\n\n if (this.dateOptionsInput.iso) {\n output.iso = dayjsObject.toISOString();\n }\n\n return output;\n }\n\n /**\n * Transform localized value\n */\n protected transformLocalized(value: LocalizedObject[] | string, locale?: string) {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (!locale) {\n return value[0]?.value || value;\n }\n\n return value.find((item) => item.localeCode === locale)?.value;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"resource-field-builder.mjs","names":[],"sources":["../../../../../../../core/src/resource/resource-field-builder.ts"],"sourcesContent":["import { isObject } from \"@mongez/supportive-is\";\nimport dayjs from \"dayjs\";\nimport relativeTime from \"dayjs/plugin/relativeTime.js\";\nimport { storage } from \"../storage\";\n\n// `humanTime` date options call dayjs(...).fromNow(), which lives in the\n// relativeTime plugin. dayjs.extend is idempotent (a plugin registers itself\n// once), so extending here at module load is safe to repeat.\ndayjs.extend(relativeTime);\nimport { uploadsUrl, url } from \"../utils/urls\";\nimport { type LocalizedObject } from \"./../utils/get-localized\";\nimport {\n type ResourceFieldBuilderDateOutputOptions,\n type ResourceOutputValueCastType,\n} from \"./types\";\n\nexport class ResourceFieldBuilder {\n /**\n * Field value\n */\n protected fieldValue?: unknown;\n\n /**\n * Whether the value is nullable\n * If set to false and value is null, it will be returned as undefined\n */\n protected isNullable = false;\n\n /**\n * Whether this field is an array\n * When true, transform() maps over each element using the base type\n */\n protected isArrayField = false;\n\n /**\n * Default value\n */\n protected defaultValue?: unknown;\n\n /**\n * Date format\n */\n protected dateFormat = \"DD-MM-YYYY hh:mm:ss A\";\n\n /**\n * Input key\n */\n protected inputKeyToUse?: string;\n\n /**\n * Add a condition before transforming the value\n */\n protected condition?: () => boolean;\n\n /**\n * Define how date fields are returned\n * If type of the date options is string then it will be returned as a string\n * otherwise it will be returned as an object contains the date options\n */\n protected dateOptionsInput: ResourceFieldBuilderDateOutputOptions = {\n format: true,\n timestamp: true,\n timezone: false,\n locale: false,\n offset: false,\n humanTime: true,\n iso: true,\n };\n\n /**\n * Constructor\n */\n public constructor(protected readonly type: ResourceOutputValueCastType) {\n //\n }\n\n /**\n * Parse a cast type string (including suffixes) into a configured builder.\n * Suffix order: [] before ? (e.g. \"string[]?\")\n * Parsing strips right-to-left: ? first, then [].\n */\n public static fromCastType(castType: string): ResourceFieldBuilder {\n let baseType = castType;\n let nullable = false;\n let isArray = false;\n\n if (baseType.endsWith(\"?\")) {\n nullable = true;\n baseType = baseType.slice(0, -1);\n }\n\n if (baseType.endsWith(\"[]\")) {\n isArray = true;\n baseType = baseType.slice(0, -2);\n }\n\n const builder = new ResourceFieldBuilder(baseType as ResourceOutputValueCastType);\n if (nullable) builder.nullable();\n if (isArray) builder.array();\n return builder;\n }\n\n /**\n * Set input key\n * Will be used in transformation if provided\n */\n public setInputKey(key: string) {\n this.inputKeyToUse = key;\n\n return this;\n }\n\n /**\n * Add a condition before transforming the value\n */\n public when(condition: () => boolean) {\n this.condition = condition;\n return this;\n }\n\n /**\n * Set whether the value is nullable\n */\n public nullable() {\n this.isNullable = true;\n return this;\n }\n\n /**\n * Mark this field as an array\n * transform() will map over each element using the base type\n */\n public array() {\n this.isArrayField = true;\n return this;\n }\n\n /**\n * Get input key\n */\n public getInputKey() {\n return this.inputKeyToUse;\n }\n\n /**\n * Set default value\n */\n public default(value: unknown) {\n this.defaultValue = value;\n\n return this;\n }\n\n /**\n * Set field format\n */\n public format(format: string) {\n this.dateFormat = format;\n\n return this;\n }\n\n /**\n * Set date options\n * This will override current date options\n */\n public dateOptions(options: ResourceFieldBuilderDateOutputOptions) {\n this.dateOptionsInput = options;\n\n return this;\n }\n\n /**\n * Transform the value.\n * When isArrayField is true, maps over each element using transformSingleValue.\n */\n public transform(value: any, locale?: string) {\n if (this.isArrayField) {\n if (!Array.isArray(value)) {\n return this.isNullable ? null : [];\n }\n\n return value\n .map((item) => this.transformSingleValue(item, locale))\n .filter((v) => v !== undefined);\n }\n\n return this.transformSingleValue(value, locale);\n }\n\n /**\n * Transform a single value according to the base type.\n */\n protected transformSingleValue(value: any, locale?: string) {\n if (value === undefined || value === null) {\n return this.isNullable ? null : this.defaultValue;\n }\n\n if (this.condition && !this.condition()) {\n return this.isNullable ? null : this.defaultValue;\n }\n\n switch (this.type) {\n case \"string\":\n return String(value);\n case \"number\": {\n const num = Number(value);\n return isNaN(num) ? (this.isNullable ? null : undefined) : num;\n }\n case \"boolean\":\n return Boolean(value);\n case \"float\": {\n const float = parseFloat(value);\n return isNaN(float) ? (this.isNullable ? null : undefined) : float;\n }\n\n case \"int\": {\n const int = parseInt(value);\n return isNaN(int) ? (this.isNullable ? null : undefined) : int;\n }\n\n case \"date\":\n return this.transformDate(value as string | Date, locale);\n case \"localized\":\n return this.transformLocalized(value as LocalizedObject[], locale);\n case \"url\":\n return url(value as string);\n case \"uploadsUrl\":\n return uploadsUrl(value as string);\n case \"storageUrl\":\n return storage.url(value as string);\n case \"object\":\n return isObject(value) && !Array.isArray(value) && Object.keys(value).length > 0\n ? value\n : this.isNullable\n ? null\n : undefined;\n case \"array\":\n return Array.isArray(value) ? value : this.isNullable ? null : undefined;\n }\n }\n\n /**\n * Transform date value\n */\n protected transformDate(value: string | Date, locale?: string) {\n if (typeof this.dateOptionsInput === \"string\") {\n if (this.dateOptionsInput === \"format\") {\n return dayjs(value).format(this.dateFormat);\n }\n\n if (this.dateOptionsInput === \"iso\") {\n return dayjs(value).toISOString();\n }\n\n if (this.dateOptionsInput === \"timestamp\") {\n return dayjs(value).valueOf();\n }\n\n if (this.dateOptionsInput === \"humanTime\") {\n return (dayjs as any)(value).fromNow();\n }\n\n if (this.dateOptionsInput === \"locale\") {\n if (!locale) {\n return dayjs(value).format(this.dateFormat);\n }\n\n return dayjs(value).locale(locale).format(this.dateFormat);\n }\n }\n\n // now manage it as an object based on date options what's marked as true\n const output: {\n format?: string;\n timestamp?: number;\n humanTime?: string;\n locale?: string;\n iso?: string;\n } = {};\n\n let dayjsObject = dayjs((value as any)?.iso || value);\n\n if (locale) {\n dayjsObject = dayjsObject.locale(locale);\n }\n\n if (this.dateOptionsInput.iso) {\n output.iso = dayjsObject.toISOString();\n }\n\n if (this.dateOptionsInput.format) {\n output.format = dayjsObject.format(this.dateFormat);\n }\n\n if (this.dateOptionsInput.timestamp) {\n output.timestamp = dayjsObject.valueOf();\n }\n\n if (this.dateOptionsInput.humanTime) {\n output.humanTime = (dayjsObject as any).fromNow();\n }\n\n if (this.dateOptionsInput.locale) {\n output.locale = dayjsObject.format(this.dateFormat);\n }\n\n if (this.dateOptionsInput.iso) {\n output.iso = dayjsObject.toISOString();\n }\n\n return output;\n }\n\n /**\n * Transform localized value\n */\n protected transformLocalized(value: LocalizedObject[] | string, locale?: string) {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (!locale) {\n return value[0]?.value || value;\n }\n\n return value.find((item) => item.localeCode === locale)?.value;\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.mts","names":[],"sources":["../../../../../../../core/src/resource/types.ts"],"mappings":";;;;;;KAKY,2BAAA;;;AAAZ;;;;AAAuC;AAsBvC;;KAAY,qBAAA;;AAAqB;AAQjC;;;;KAAY,gBAAA,GACR,2BAAA,MACG,2BAAA,UACA,2BAAA,SACA,2BAAA;AAAA,KAEK,mBAAA;EACV,MAAA;EACA,MAAA,EAAQ,MAAM,SAAS,mBAAA;AAAA;AAAA,KAGb,mBAAA,GACR,gBAAA,GACA,mBAAA,GACA,qBAAA,GACA,IAAA,CAAK,mBAAA,aACI,gBAAA,IACT,oBAAA,GACA,mBAAA,KACE,KAAA,OAAY,QAAA,EAAU,gBAAA;AAAA,KAEhB,cAAA,GAAiB,MAAM,SAAS,mBAAA;AAAA,KAEhC,qCAAA;EAnBL;;AAA2B;EAwB5B,MAAA;EAtByB;;;EA0BzB,SAAA;EAxBJ;;;EA4BI,SAAA;EA5BsC;AAG5C;;EA6BM,QAAA;EA5BF;;;EAgCE,MAAA;EA7BF;;;EAiCE,MAAA;EA7BsB;;;EAiCtB,GAAA;AAAA;;;;;;;KAcM,iBAAA,GACR,2BAAA,GACA,mBAAA,IACC,mBAAA;;;;AAlDuC;KAwDhC,cAAA,oBACK,cAAA;EACb,IAAA,EAAM,MAAA,SAAe,iBAAA;AAAA"}
1
+ {"version":3,"file":"types.d.mts","names":[],"sources":["../../../../../../../core/src/resource/types.ts"],"mappings":";;;;;;KAKY,2BAAA;;;AAAZ;;;;AAAuC;AAsBvC;;KAAY,qBAAA;;AAAqB;AAQjC;;;;KAAY,gBAAA,GACR,2BAAA,MACG,2BAAA,UACA,2BAAA,SACA,2BAAA;AAAA,KAEK,mBAAA;EACV,MAAA;EACA,MAAA,EAAQ,MAAM,SAAS,mBAAA;AAAA;AAAA,KAGb,mBAAA,GACR,gBAAA,GACA,mBAAA,GACA,qBAAA,GACA,IAAA,CAAK,mBAAA,aACI,gBAAA,IACT,oBAAA,GACA,mBAAA,KACE,KAAA,OAAY,QAAA,EAAU,gBAAA;AAAA,KAEhB,cAAA,GAAiB,MAAM,SAAS,mBAAA;AAAA,KAEhC,qCAAA;EAnBL;;AAA2B;EAwB5B,MAAA;EAtByB;;;EA0BzB,SAAA;EAxBJ;;;EA4BI,SAAA;EA5BsC;AAG5C;;EA6BM,QAAA;EA5BF;;;EAgCE,MAAA;EA7BF;;;EAiCE,MAAA;EA7BsB;;;EAiCtB,GAAA;AAAA;;;;;;;KAcM,iBAAA,GACV,2BAAA,GAA8B,mBAAA,IAAuB,mBAAA;;;;AAhDX;KAsDhC,cAAA,oBACK,cAAA;EACb,IAAA,EAAM,MAAA,SAAe,iBAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"positional-handler-diagnostics.d.mts","names":[],"sources":["../../../../../../../core/src/router/positional-handler-diagnostics.ts"],"mappings":";;;;AAyPsE;AAmBtE;;AAnBsE,KArN1D,wBAAA;EAwOsE,kDAtOhF,MAAA,EAAQ,KAAK,YA+OC;EA5Od,IAAA;EAGA,WAAA,UAyOgE;EAtOhE,UAAA;AAAA;;;AAkP4C;AAS9C;;;;AAAkF;AAclF;;;;;;;;;;;;;AAAsF;;;;;;;;;;;iBAhGtE,0BAAA,CAA2B,OAAgB;;;;;;;;;iBA+B3C,uBAAA,CACd,OAAA,WACA,KAAA;EAAS,MAAA,EAAQ,KAAK;EAAY,IAAA;EAAc,UAAA;AAAA;;;;iBAmBlC,6BAAA,aAA0C,wBAAwB;;;;;;iBASlE,+BAAA,CAAgC,UAAkB;;;;;iBAYlD,8BAAA;;;;;;iBASA,gCAAA,CAAiC,OAAiC,EAAxB,wBAAwB;;;;;;;iBAclE,+BAAA,CAAgC,MAAA,GAAQ,IAAA,QAAY,GAAA,YAAkB,wBAAA"}
1
+ {"version":3,"file":"positional-handler-diagnostics.d.mts","names":[],"sources":["../../../../../../../core/src/router/positional-handler-diagnostics.ts"],"mappings":";;;;AA+PsE;AAmBtE;;AAnBsE,KA3N1D,wBAAA;EA8OsE,kDA5OhF,MAAA,EAAQ,KAAK,YAqPC;EAlPd,IAAA;EAGA,WAAA,UA+OgE;EA5OhE,UAAA;AAAA;;;AA0P4C;AAS9C;;;;AAAkF;AAclF;;;;;;;;;;;;;AAAsF;;;;;;;;;;;iBApGtE,0BAAA,CAA2B,OAAgB;;;;;;;;;iBAiC3C,uBAAA,CACd,OAAA,WACA,KAAA;EAAS,MAAA,EAAQ,KAAK;EAAY,IAAA;EAAc,UAAA;AAAA;;;;iBAmBlC,6BAAA,aAA0C,wBAAwB;;;;;;iBASlE,+BAAA,CAAgC,UAAkB;;;;;iBAclD,8BAAA;;;;;;iBASA,gCAAA,CAAiC,OAAiC,EAAxB,wBAAwB;;;;;;;iBAclE,+BAAA,CAAgC,MAAA,GAAQ,IAAA,QAAY,GAAA,YAAkB,wBAAA"}
@@ -114,7 +114,10 @@ function readParameterList(handler) {
114
114
  if (source.includes("[native code]")) return void 0;
115
115
  if (/^\s*class[\s{]/.test(source)) return void 0;
116
116
  const bareArrow = source.match(/^\s*(?:async\s+)?([A-Za-z_$][\w$]*)\s*=>/);
117
- if (bareArrow) return [bareArrow[1]];
117
+ if (bareArrow) {
118
+ const parameter = bareArrow[1];
119
+ return parameter === void 0 ? void 0 : [parameter];
120
+ }
118
121
  const openIndex = source.indexOf("(");
119
122
  if (openIndex === -1) return void 0;
120
123
  return splitTopLevelParameters(source, openIndex);
@@ -162,7 +165,10 @@ function isDestructured(parameter) {
162
165
  function looksLikePositionalHandler(handler) {
163
166
  if (typeof handler !== "function") return false;
164
167
  const parameters = readParameterList(handler);
165
- if (parameters) return parameters.length >= 2 && !isDestructured(parameters[0]);
168
+ if (parameters) {
169
+ const firstParameter = parameters[0];
170
+ return parameters.length >= 2 && firstParameter !== void 0 && !isDestructured(firstParameter);
171
+ }
166
172
  return handler.length >= 2;
167
173
  }
168
174
  /**
@@ -206,7 +212,7 @@ function listPositionalHandlerSuspects() {
206
212
  * not keep reporting the version it replaced.
207
213
  */
208
214
  function forgetPositionalHandlerSuspects(sourceFile) {
209
- for (let index = suspects.length - 1; index >= 0; index--) if (suspects[index].sourceFile === sourceFile) suspects.splice(index, 1);
215
+ for (let index = suspects.length - 1; index >= 0; index--) if (suspects[index]?.sourceFile === sourceFile) suspects.splice(index, 1);
210
216
  }
211
217
  /**
212
218
  * Drop every recorded suspect. Intended for tests, which share the router
@@ -1 +1 @@
1
- {"version":3,"file":"positional-handler-diagnostics.mjs","names":[],"sources":["../../../../../../../core/src/router/positional-handler-diagnostics.ts"],"sourcesContent":["/**\n * Early detection of route handlers still written against the **v4 positional\n * signature** — `(request, response)` — after v5 moved to a single context\n * object, `({ request, response })`.\n *\n * ## Why this exists\n *\n * A v4 handler is not rejected anywhere. It registers fine, and the router\n * calls it with one argument, so `response` is simply `undefined`. The app only\n * breaks on the first request that reaches it, with:\n *\n * TypeError: Cannot read properties of undefined (reading 'success')\n *\n * That message names nothing the reader can act on — not the route, not the\n * handler, not the change to make. This module turns that late, opaque failure\n * into one explicit list printed at boot, and into a `warlock doctor` check.\n *\n * The break itself is intentional; nothing here restores the positional form.\n * Detection and diagnostics only.\n *\n * ## Why it warns and never throws\n *\n * The signal is a heuristic (see {@link looksLikePositionalHandler}), so a\n * false positive is possible in principle. Turning one into a boot failure\n * would take a working application down over a guess, which is strictly worse\n * than the problem being diagnosed. Everything on this path is therefore a\n * warning: nothing here throws, and nothing here changes how a handler is\n * called. A miss simply degrades to the old runtime `TypeError`.\n */\n\nimport { log } from \"@warlock.js/logger\";\nimport type { Route } from \"./types\";\n\n/**\n * One route whose handler looks like it was written for v4.\n */\nexport type PositionalHandlerSuspect = {\n /** HTTP method the route was registered under. */\n method: Route[\"method\"];\n\n /** Full route path, prefixes already applied. */\n path: string;\n\n /** Handler function name, or `\"(anonymous)\"` when it has none. */\n handlerName: string;\n\n /** Route file the route came from, when the router knows it. */\n sourceFile: string;\n};\n\n/**\n * Collected across the whole registration pass so the warning can be emitted\n * ONCE, as a single list, rather than one line per route (or — as before — one\n * mystery 500 per request).\n */\nconst suspects: PositionalHandlerSuspect[] = [];\n\n/**\n * Split the parameter list of a function's source into top-level parameters.\n *\n * Depth-aware and quote-aware, because a default value may itself contain\n * commas, parentheses, braces or strings — `(request, response = f(a, b))` is\n * two parameters, not three. Anything unbalanced returns `undefined`: refusing\n * to guess is what keeps a parse quirk from becoming a false warning.\n *\n * @param openIndex index of the `(` that opens the parameter list.\n */\nfunction splitTopLevelParameters(source: string, openIndex: number): string[] | undefined {\n const parameters: string[] = [];\n\n let depth = 0;\n let current = \"\";\n let quote = \"\";\n\n for (let index = openIndex; index < source.length; index++) {\n const char = source[index];\n\n if (quote) {\n if (char === \"\\\\\") {\n current += char + (source[index + 1] ?? \"\");\n index++;\n continue;\n }\n\n if (char === quote) {\n quote = \"\";\n }\n\n current += char;\n continue;\n }\n\n if (char === '\"' || char === \"'\" || char === \"`\") {\n quote = char;\n current += char;\n continue;\n }\n\n if (char === \"(\" || char === \"[\" || char === \"{\") {\n depth++;\n\n // The paren that opens the list is punctuation, not part of a parameter.\n if (depth === 1) continue;\n\n current += char;\n continue;\n }\n\n if (char === \")\" || char === \"]\" || char === \"}\") {\n depth--;\n\n if (depth === 0) {\n if (current.trim()) {\n parameters.push(current.trim());\n }\n\n return parameters;\n }\n\n current += char;\n continue;\n }\n\n if (char === \",\" && depth === 1) {\n parameters.push(current.trim());\n current = \"\";\n continue;\n }\n\n current += char;\n }\n\n // Never found the closing paren — treat the source as unreadable.\n return undefined;\n}\n\n/**\n * Read a function's declared parameters from its own source.\n *\n * Returns `undefined` whenever the source cannot be trusted, which callers must\n * treat as \"no information\" rather than \"no parameters\":\n *\n * - `Function.prototype.bind` replaces the body with `[native code]`, so every\n * `[Controller, \"method\"]` tuple handler lands here (the router binds them);\n * - native functions likewise;\n * - a class, whose first `(` belongs to a constructor or a method, not to a\n * parameter list;\n * - anything that fails to parse.\n */\nfunction readParameterList(handler: Function): string[] | undefined {\n let source: string;\n\n try {\n source = Function.prototype.toString.call(handler);\n } catch {\n return undefined;\n }\n\n if (source.includes(\"[native code]\")) return undefined;\n\n if (/^\\s*class[\\s{]/.test(source)) return undefined;\n\n // A single parameter needs no parentheses: `ctx => …`, `async ctx => …`.\n const bareArrow = source.match(/^\\s*(?:async\\s+)?([A-Za-z_$][\\w$]*)\\s*=>/);\n\n if (bareArrow) return [bareArrow[1]];\n\n const openIndex = source.indexOf(\"(\");\n\n if (openIndex === -1) return undefined;\n\n return splitTopLevelParameters(source, openIndex);\n}\n\n/**\n * Whether a parameter is written as a destructuring pattern — `{ request }` or\n * `[a, b]` — as opposed to a plain name.\n */\nfunction isDestructured(parameter: string) {\n const start = parameter.trimStart();\n\n return start.startsWith(\"{\") || start.startsWith(\"[\");\n}\n\n/**\n * Does this handler look like it was written for the v4 positional signature?\n *\n * ## The signal, and what it misses\n *\n * `Function.length` alone is not enough, because it stops counting at the first\n * defaulted parameter:\n *\n * | handler | `.length` | actually |\n * | ---------------------------------- | --------- | -------- |\n * | `({ request, response }) => …` | 1 | v5 |\n * | `(ctx) => …` | 1 | v5 |\n * | `(request, response) => …` | 2 | v4 |\n * | `(request, response = x) => …` | 1 | v4 |\n *\n * So the primary signal is the function's own source: a handler is suspect when\n * it declares **two or more** parameters and the first is **not** destructured.\n * Reading the source catches the defaulted row that arity cannot, and rules out\n * the `({ … }, extra)` shape that arity would wrongly flag.\n *\n * When the source is unreadable — a bound or native function — this falls back\n * to `handler.length >= 2`, which `bind` preserves. That is a weaker signal but\n * never a wrong one for the common cases; it only loses the defaulted row.\n *\n * ## What is still missed, by design\n *\n * A one-parameter v4 handler (`(request) => …`) is indistinguishable from a v5\n * `(ctx) => …` and is deliberately not flagged — guessing there would produce\n * false positives on correct code. False positives against the canonical\n * `({ … })` form are essentially nil, and every miss simply leaves today's\n * behaviour in place.\n */\nexport function looksLikePositionalHandler(handler: unknown): boolean {\n if (typeof handler !== \"function\") return false;\n\n const parameters = readParameterList(handler);\n\n if (parameters) {\n return parameters.length >= 2 && !isDestructured(parameters[0]);\n }\n\n return handler.length >= 2;\n}\n\n/**\n * The name to print for a handler.\n *\n * `Function.bind` prefixes the name with `\"bound \"`, and the router binds every\n * `[Controller, \"method\"]` tuple handler. The bare method name is what the user\n * actually wrote, so that is what gets printed.\n */\nfunction handlerDisplayName(handler: Function): string {\n return handler.name?.replace(/^bound /, \"\").trim() || \"(anonymous)\";\n}\n\n/**\n * Inspect one route's handler as it registers, recording it when it looks like\n * the v4 positional form. Called from `Router.add`, so the cost is paid once per\n * route at registration and never per request.\n *\n * Deliberately total: any unexpected failure in the heuristic is swallowed, so a\n * diagnostic can never be the reason a route fails to register.\n */\nexport function inspectHandlerSignature(\n handler: unknown,\n route: { method: Route[\"method\"]; path: string; sourceFile: string },\n) {\n try {\n if (!looksLikePositionalHandler(handler)) return;\n\n suspects.push({\n method: route.method,\n path: route.path,\n handlerName: handlerDisplayName(handler as Function),\n sourceFile: route.sourceFile,\n });\n } catch {\n // A diagnostic must never break registration.\n }\n}\n\n/**\n * Every suspect recorded so far, in registration order.\n */\nexport function listPositionalHandlerSuspects(): readonly PositionalHandlerSuspect[] {\n return suspects;\n}\n\n/**\n * Drop the suspects belonging to a route file. Kept in step with\n * `Router.removeRoutesBySourceFile` so an HMR reload that fixes a handler does\n * not keep reporting the version it replaced.\n */\nexport function forgetPositionalHandlerSuspects(sourceFile: string) {\n for (let index = suspects.length - 1; index >= 0; index--) {\n if (suspects[index].sourceFile === sourceFile) {\n suspects.splice(index, 1);\n }\n }\n}\n\n/**\n * Drop every recorded suspect. Intended for tests, which share the router\n * singleton.\n */\nexport function clearPositionalHandlerSuspects() {\n suspects.length = 0;\n}\n\n/**\n * The one-line diagnostic for a single route. Written for someone who has never\n * read Warlock's internals: it names the handler, the route, what is wrong, and\n * the exact edit that fixes it.\n */\nexport function describePositionalHandlerSuspect(suspect: PositionalHandlerSuspect): string {\n return (\n `Handler \"${suspect.handlerName}\" (${suspect.method} ${suspect.path}) looks like ` +\n `the v4 positional signature (request, response). ` +\n `v5 passes a single context object — change it to ({ request, response }).`\n );\n}\n\n/**\n * The full boot-time warning: every suspect, once, in one entry.\n *\n * One boot, one list — not one warning per route, and emphatically not one 500\n * per request. Returns the reported suspects so callers can assert on them.\n */\nexport function reportPositionalHandlerSuspects(logger: Pick<typeof log, \"warn\"> = log) {\n const reported = [...suspects];\n\n if (reported.length === 0) return reported;\n\n const headline =\n reported.length === 1\n ? \"1 route handler looks like the v4 positional signature.\"\n : `${reported.length} route handlers look like the v4 positional signature.`;\n\n logger.warn({\n module: \"router\",\n action: \"handlerSignature\",\n message:\n `${headline} Warlock v5 calls every route handler with a single context object, ` +\n `so a second parameter is always undefined and the request fails as soon as it is used:\\n` +\n reported.map((suspect) => ` - ${describePositionalHandlerSuspect(suspect)}`).join(\"\\n\"),\n context: { handlers: reported },\n });\n\n return reported;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuDA,MAAM,WAAuC,CAAC;;;;;;;;;;;AAY9C,SAAS,wBAAwB,QAAgB,WAAyC;CACxF,MAAM,aAAuB,CAAC;CAE9B,IAAI,QAAQ;CACZ,IAAI,UAAU;CACd,IAAI,QAAQ;CAEZ,KAAK,IAAI,QAAQ,WAAW,QAAQ,OAAO,QAAQ,SAAS;EAC1D,MAAM,OAAO,OAAO;EAEpB,IAAI,OAAO;GACT,IAAI,SAAS,MAAM;IACjB,WAAW,QAAQ,OAAO,QAAQ,MAAM;IACxC;IACA;GACF;GAEA,IAAI,SAAS,OACX,QAAQ;GAGV,WAAW;GACX;EACF;EAEA,IAAI,SAAS,QAAO,SAAS,OAAO,SAAS,KAAK;GAChD,QAAQ;GACR,WAAW;GACX;EACF;EAEA,IAAI,SAAS,OAAO,SAAS,OAAO,SAAS,KAAK;GAChD;GAGA,IAAI,UAAU,GAAG;GAEjB,WAAW;GACX;EACF;EAEA,IAAI,SAAS,OAAO,SAAS,OAAO,SAAS,KAAK;GAChD;GAEA,IAAI,UAAU,GAAG;IACf,IAAI,QAAQ,KAAK,GACf,WAAW,KAAK,QAAQ,KAAK,CAAC;IAGhC,OAAO;GACT;GAEA,WAAW;GACX;EACF;EAEA,IAAI,SAAS,OAAO,UAAU,GAAG;GAC/B,WAAW,KAAK,QAAQ,KAAK,CAAC;GAC9B,UAAU;GACV;EACF;EAEA,WAAW;CACb;AAIF;;;;;;;;;;;;;;AAeA,SAAS,kBAAkB,SAAyC;CAClE,IAAI;CAEJ,IAAI;EACF,SAAS,SAAS,UAAU,SAAS,KAAK,OAAO;CACnD,QAAQ;EACN;CACF;CAEA,IAAI,OAAO,SAAS,eAAe,GAAG,OAAO;CAE7C,IAAI,iBAAiB,KAAK,MAAM,GAAG,OAAO;CAG1C,MAAM,YAAY,OAAO,MAAM,0CAA0C;CAEzE,IAAI,WAAW,OAAO,CAAC,UAAU,EAAE;CAEnC,MAAM,YAAY,OAAO,QAAQ,GAAG;CAEpC,IAAI,cAAc,IAAI,OAAO;CAE7B,OAAO,wBAAwB,QAAQ,SAAS;AAClD;;;;;AAMA,SAAS,eAAe,WAAmB;CACzC,MAAM,QAAQ,UAAU,UAAU;CAElC,OAAO,MAAM,WAAW,GAAG,KAAK,MAAM,WAAW,GAAG;AACtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCA,SAAgB,2BAA2B,SAA2B;CACpE,IAAI,OAAO,YAAY,YAAY,OAAO;CAE1C,MAAM,aAAa,kBAAkB,OAAO;CAE5C,IAAI,YACF,OAAO,WAAW,UAAU,KAAK,CAAC,eAAe,WAAW,EAAE;CAGhE,OAAO,QAAQ,UAAU;AAC3B;;;;;;;;AASA,SAAS,mBAAmB,SAA2B;CACrD,OAAO,QAAQ,MAAM,QAAQ,WAAW,EAAE,CAAC,CAAC,KAAK,KAAK;AACxD;;;;;;;;;AAUA,SAAgB,wBACd,SACA,OACA;CACA,IAAI;EACF,IAAI,CAAC,2BAA2B,OAAO,GAAG;EAE1C,SAAS,KAAK;GACZ,QAAQ,MAAM;GACd,MAAM,MAAM;GACZ,aAAa,mBAAmB,OAAmB;GACnD,YAAY,MAAM;EACpB,CAAC;CACH,QAAQ,CAER;AACF;;;;AAKA,SAAgB,gCAAqE;CACnF,OAAO;AACT;;;;;;AAOA,SAAgB,gCAAgC,YAAoB;CAClE,KAAK,IAAI,QAAQ,SAAS,SAAS,GAAG,SAAS,GAAG,SAChD,IAAI,SAAS,MAAM,CAAC,eAAe,YACjC,SAAS,OAAO,OAAO,CAAC;AAG9B;;;;;AAMA,SAAgB,iCAAiC;CAC/C,SAAS,SAAS;AACpB;;;;;;AAOA,SAAgB,iCAAiC,SAA2C;CAC1F,OACE,YAAY,QAAQ,YAAY,KAAK,QAAQ,OAAO,GAAG,QAAQ,KAAK;AAIxE;;;;;;;AAQA,SAAgB,gCAAgC,SAAmC,KAAK;CACtF,MAAM,WAAW,CAAC,GAAG,QAAQ;CAE7B,IAAI,SAAS,WAAW,GAAG,OAAO;CAElC,MAAM,WACJ,SAAS,WAAW,IAChB,4DACA,GAAG,SAAS,OAAO;CAEzB,OAAO,KAAK;EACV,QAAQ;EACR,QAAQ;EACR,SACE,GAAG,SAAS,gKAEZ,SAAS,KAAK,YAAY,OAAO,iCAAiC,OAAO,GAAG,CAAC,CAAC,KAAK,IAAI;EACzF,SAAS,EAAE,UAAU,SAAS;CAChC,CAAC;CAED,OAAO;AACT"}
1
+ {"version":3,"file":"positional-handler-diagnostics.mjs","names":[],"sources":["../../../../../../../core/src/router/positional-handler-diagnostics.ts"],"sourcesContent":["/**\n * Early detection of route handlers still written against the **v4 positional\n * signature** — `(request, response)` — after v5 moved to a single context\n * object, `({ request, response })`.\n *\n * ## Why this exists\n *\n * A v4 handler is not rejected anywhere. It registers fine, and the router\n * calls it with one argument, so `response` is simply `undefined`. The app only\n * breaks on the first request that reaches it, with:\n *\n * TypeError: Cannot read properties of undefined (reading 'success')\n *\n * That message names nothing the reader can act on — not the route, not the\n * handler, not the change to make. This module turns that late, opaque failure\n * into one explicit list printed at boot, and into a `warlock doctor` check.\n *\n * The break itself is intentional; nothing here restores the positional form.\n * Detection and diagnostics only.\n *\n * ## Why it warns and never throws\n *\n * The signal is a heuristic (see {@link looksLikePositionalHandler}), so a\n * false positive is possible in principle. Turning one into a boot failure\n * would take a working application down over a guess, which is strictly worse\n * than the problem being diagnosed. Everything on this path is therefore a\n * warning: nothing here throws, and nothing here changes how a handler is\n * called. A miss simply degrades to the old runtime `TypeError`.\n */\n\nimport { log } from \"@warlock.js/logger\";\nimport type { Route } from \"./types\";\n\n/**\n * One route whose handler looks like it was written for v4.\n */\nexport type PositionalHandlerSuspect = {\n /** HTTP method the route was registered under. */\n method: Route[\"method\"];\n\n /** Full route path, prefixes already applied. */\n path: string;\n\n /** Handler function name, or `\"(anonymous)\"` when it has none. */\n handlerName: string;\n\n /** Route file the route came from, when the router knows it. */\n sourceFile: string;\n};\n\n/**\n * Collected across the whole registration pass so the warning can be emitted\n * ONCE, as a single list, rather than one line per route (or — as before — one\n * mystery 500 per request).\n */\nconst suspects: PositionalHandlerSuspect[] = [];\n\n/**\n * Split the parameter list of a function's source into top-level parameters.\n *\n * Depth-aware and quote-aware, because a default value may itself contain\n * commas, parentheses, braces or strings — `(request, response = f(a, b))` is\n * two parameters, not three. Anything unbalanced returns `undefined`: refusing\n * to guess is what keeps a parse quirk from becoming a false warning.\n *\n * @param openIndex index of the `(` that opens the parameter list.\n */\nfunction splitTopLevelParameters(source: string, openIndex: number): string[] | undefined {\n const parameters: string[] = [];\n\n let depth = 0;\n let current = \"\";\n let quote = \"\";\n\n for (let index = openIndex; index < source.length; index++) {\n const char = source[index];\n\n if (quote) {\n if (char === \"\\\\\") {\n current += char + (source[index + 1] ?? \"\");\n index++;\n continue;\n }\n\n if (char === quote) {\n quote = \"\";\n }\n\n current += char;\n continue;\n }\n\n if (char === '\"' || char === \"'\" || char === \"`\") {\n quote = char;\n current += char;\n continue;\n }\n\n if (char === \"(\" || char === \"[\" || char === \"{\") {\n depth++;\n\n // The paren that opens the list is punctuation, not part of a parameter.\n if (depth === 1) continue;\n\n current += char;\n continue;\n }\n\n if (char === \")\" || char === \"]\" || char === \"}\") {\n depth--;\n\n if (depth === 0) {\n if (current.trim()) {\n parameters.push(current.trim());\n }\n\n return parameters;\n }\n\n current += char;\n continue;\n }\n\n if (char === \",\" && depth === 1) {\n parameters.push(current.trim());\n current = \"\";\n continue;\n }\n\n current += char;\n }\n\n // Never found the closing paren — treat the source as unreadable.\n return undefined;\n}\n\n/**\n * Read a function's declared parameters from its own source.\n *\n * Returns `undefined` whenever the source cannot be trusted, which callers must\n * treat as \"no information\" rather than \"no parameters\":\n *\n * - `Function.prototype.bind` replaces the body with `[native code]`, so every\n * `[Controller, \"method\"]` tuple handler lands here (the router binds them);\n * - native functions likewise;\n * - a class, whose first `(` belongs to a constructor or a method, not to a\n * parameter list;\n * - anything that fails to parse.\n */\nfunction readParameterList(handler: Function): string[] | undefined {\n let source: string;\n\n try {\n source = Function.prototype.toString.call(handler);\n } catch {\n return undefined;\n }\n\n if (source.includes(\"[native code]\")) return undefined;\n\n if (/^\\s*class[\\s{]/.test(source)) return undefined;\n\n // A single parameter needs no parentheses: `ctx => …`, `async ctx => …`.\n const bareArrow = source.match(/^\\s*(?:async\\s+)?([A-Za-z_$][\\w$]*)\\s*=>/);\n\n if (bareArrow) {\n const parameter = bareArrow[1];\n\n return parameter === undefined ? undefined : [parameter];\n }\n\n const openIndex = source.indexOf(\"(\");\n\n if (openIndex === -1) return undefined;\n\n return splitTopLevelParameters(source, openIndex);\n}\n\n/**\n * Whether a parameter is written as a destructuring pattern — `{ request }` or\n * `[a, b]` — as opposed to a plain name.\n */\nfunction isDestructured(parameter: string) {\n const start = parameter.trimStart();\n\n return start.startsWith(\"{\") || start.startsWith(\"[\");\n}\n\n/**\n * Does this handler look like it was written for the v4 positional signature?\n *\n * ## The signal, and what it misses\n *\n * `Function.length` alone is not enough, because it stops counting at the first\n * defaulted parameter:\n *\n * | handler | `.length` | actually |\n * | ---------------------------------- | --------- | -------- |\n * | `({ request, response }) => …` | 1 | v5 |\n * | `(ctx) => …` | 1 | v5 |\n * | `(request, response) => …` | 2 | v4 |\n * | `(request, response = x) => …` | 1 | v4 |\n *\n * So the primary signal is the function's own source: a handler is suspect when\n * it declares **two or more** parameters and the first is **not** destructured.\n * Reading the source catches the defaulted row that arity cannot, and rules out\n * the `({ … }, extra)` shape that arity would wrongly flag.\n *\n * When the source is unreadable — a bound or native function — this falls back\n * to `handler.length >= 2`, which `bind` preserves. That is a weaker signal but\n * never a wrong one for the common cases; it only loses the defaulted row.\n *\n * ## What is still missed, by design\n *\n * A one-parameter v4 handler (`(request) => …`) is indistinguishable from a v5\n * `(ctx) => …` and is deliberately not flagged — guessing there would produce\n * false positives on correct code. False positives against the canonical\n * `({ … })` form are essentially nil, and every miss simply leaves today's\n * behaviour in place.\n */\nexport function looksLikePositionalHandler(handler: unknown): boolean {\n if (typeof handler !== \"function\") return false;\n\n const parameters = readParameterList(handler);\n\n if (parameters) {\n const firstParameter = parameters[0];\n\n return parameters.length >= 2 && firstParameter !== undefined && !isDestructured(firstParameter);\n }\n\n return handler.length >= 2;\n}\n\n/**\n * The name to print for a handler.\n *\n * `Function.bind` prefixes the name with `\"bound \"`, and the router binds every\n * `[Controller, \"method\"]` tuple handler. The bare method name is what the user\n * actually wrote, so that is what gets printed.\n */\nfunction handlerDisplayName(handler: Function): string {\n return handler.name?.replace(/^bound /, \"\").trim() || \"(anonymous)\";\n}\n\n/**\n * Inspect one route's handler as it registers, recording it when it looks like\n * the v4 positional form. Called from `Router.add`, so the cost is paid once per\n * route at registration and never per request.\n *\n * Deliberately total: any unexpected failure in the heuristic is swallowed, so a\n * diagnostic can never be the reason a route fails to register.\n */\nexport function inspectHandlerSignature(\n handler: unknown,\n route: { method: Route[\"method\"]; path: string; sourceFile: string },\n) {\n try {\n if (!looksLikePositionalHandler(handler)) return;\n\n suspects.push({\n method: route.method,\n path: route.path,\n handlerName: handlerDisplayName(handler as Function),\n sourceFile: route.sourceFile,\n });\n } catch {\n // A diagnostic must never break registration.\n }\n}\n\n/**\n * Every suspect recorded so far, in registration order.\n */\nexport function listPositionalHandlerSuspects(): readonly PositionalHandlerSuspect[] {\n return suspects;\n}\n\n/**\n * Drop the suspects belonging to a route file. Kept in step with\n * `Router.removeRoutesBySourceFile` so an HMR reload that fixes a handler does\n * not keep reporting the version it replaced.\n */\nexport function forgetPositionalHandlerSuspects(sourceFile: string) {\n for (let index = suspects.length - 1; index >= 0; index--) {\n const suspect = suspects[index];\n\n if (suspect?.sourceFile === sourceFile) {\n suspects.splice(index, 1);\n }\n }\n}\n\n/**\n * Drop every recorded suspect. Intended for tests, which share the router\n * singleton.\n */\nexport function clearPositionalHandlerSuspects() {\n suspects.length = 0;\n}\n\n/**\n * The one-line diagnostic for a single route. Written for someone who has never\n * read Warlock's internals: it names the handler, the route, what is wrong, and\n * the exact edit that fixes it.\n */\nexport function describePositionalHandlerSuspect(suspect: PositionalHandlerSuspect): string {\n return (\n `Handler \"${suspect.handlerName}\" (${suspect.method} ${suspect.path}) looks like ` +\n `the v4 positional signature (request, response). ` +\n `v5 passes a single context object — change it to ({ request, response }).`\n );\n}\n\n/**\n * The full boot-time warning: every suspect, once, in one entry.\n *\n * One boot, one list — not one warning per route, and emphatically not one 500\n * per request. Returns the reported suspects so callers can assert on them.\n */\nexport function reportPositionalHandlerSuspects(logger: Pick<typeof log, \"warn\"> = log) {\n const reported = [...suspects];\n\n if (reported.length === 0) return reported;\n\n const headline =\n reported.length === 1\n ? \"1 route handler looks like the v4 positional signature.\"\n : `${reported.length} route handlers look like the v4 positional signature.`;\n\n logger.warn({\n module: \"router\",\n action: \"handlerSignature\",\n message:\n `${headline} Warlock v5 calls every route handler with a single context object, ` +\n `so a second parameter is always undefined and the request fails as soon as it is used:\\n` +\n reported.map((suspect) => ` - ${describePositionalHandlerSuspect(suspect)}`).join(\"\\n\"),\n context: { handlers: reported },\n });\n\n return reported;\n}\n"],"mappings":"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"}
@@ -53,7 +53,7 @@ var RouteRegistry = class {
53
53
  * @returns Matched route with extracted params, or null if no match
54
54
  */
55
55
  find(method, url) {
56
- const path = normalizeRequestPath(url.split("?")[0]);
56
+ const path = normalizeRequestPath(url.split("?")[0] ?? "/");
57
57
  const match = this.router.find(method, path);
58
58
  if (!match) return null;
59
59
  return match.handler(null, null, match.params, match.store, {});
@@ -1 +1 @@
1
- {"version":3,"file":"route-registry.mjs","names":[],"sources":["../../../../../../../core/src/router/route-registry.ts"],"sourcesContent":["import FindMyWay, { type HTTPMethod, type Instance } from \"find-my-way\";\nimport { normalizeRequestPath } from \"./normalize-request-path\";\nimport type { RequestMethod, Route } from \"./types\";\n\n/**\n * The concrete HTTP verbs an `all` route expands into.\n * Mirrors the set Fastify's `.all()` answers in production, so `router.any()`\n * routes behave identically under the dev server and prod Fastify.\n */\nconst ALL_METHODS: Exclude<RequestMethod, \"all\">[] = [\n \"GET\",\n \"POST\",\n \"PUT\",\n \"PATCH\",\n \"DELETE\",\n \"OPTIONS\",\n \"HEAD\",\n];\n\n/**\n * Route Registry\n * Manages dynamic route matching using find-my-way for HMR support\n */\nexport class RouteRegistry {\n private router: Instance<any>;\n\n public constructor() {\n this.router = FindMyWay({\n // Request paths are normalized explicitly in `find`; leaving this off\n // makes that shared normalizer, rather than a second router option, the\n // reason development accepts a terminal slash.\n ignoreTrailingSlash: false,\n caseSensitive: false,\n });\n }\n\n /**\n * Register all routes from the router's internal list\n */\n public register(routes: Route[]): void {\n // Register each route\n for (const route of routes) {\n if (route.method === \"all\") {\n for (const method of ALL_METHODS) {\n this.registerRoute({\n ...route,\n method,\n });\n }\n } else {\n this.registerRoute(route);\n }\n }\n }\n\n /**\n * Register a single route\n */\n public registerRoute(route: Route): void {\n this.router.on(route.method as HTTPMethod, route.path, (req, res, params) => {\n // Store the route and params for later use\n return { route, params };\n });\n }\n\n /**\n * Find a matching route for the given method and URL\n * @returns Matched route with extracted params, or null if no match\n */\n public find(\n method: string,\n url: string,\n ): { route: Route; params: Record<string, string> } | null {\n // Strip query string from URL (find-my-way expects just the path)\n const path = normalizeRequestPath(url.split(\"?\")[0]);\n\n const match = this.router.find(method as HTTPMethod, path);\n\n if (!match) {\n return null;\n }\n\n // find-my-way handler expects (req, res, params, store, searchParams)\n // We only care about the return value which contains { route, params }\n return match.handler(null as any, null as any, match.params, match.store, {});\n }\n\n /**\n * Get all registered routes count (for debugging)\n */\n public getRouteCount(): number {\n return this.router\n .prettyPrint()\n .split(\"\\n\")\n .filter((line) => line.trim()).length;\n }\n}\n"],"mappings":";;;;;;;;;AASA,MAAM,cAA+C;CACnD;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;;;;AAMA,IAAa,gBAAb,MAA2B;CAGzB,AAAO,cAAc;EACnB,KAAK,SAAS,UAAU;GAItB,qBAAqB;GACrB,eAAe;EACjB,CAAC;CACH;;;;CAKA,AAAO,SAAS,QAAuB;EAErC,KAAK,MAAM,SAAS,QAClB,IAAI,MAAM,WAAW,OACnB,KAAK,MAAM,UAAU,aACnB,KAAK,cAAc;GACjB,GAAG;GACH;EACF,CAAC;OAGH,KAAK,cAAc,KAAK;CAG9B;;;;CAKA,AAAO,cAAc,OAAoB;EACvC,KAAK,OAAO,GAAG,MAAM,QAAsB,MAAM,OAAO,KAAK,KAAK,WAAW;GAE3E,OAAO;IAAE;IAAO;GAAO;EACzB,CAAC;CACH;;;;;CAMA,AAAO,KACL,QACA,KACyD;EAEzD,MAAM,OAAO,qBAAqB,IAAI,MAAM,GAAG,CAAC,CAAC,EAAE;EAEnD,MAAM,QAAQ,KAAK,OAAO,KAAK,QAAsB,IAAI;EAEzD,IAAI,CAAC,OACH,OAAO;EAKT,OAAO,MAAM,QAAQ,MAAa,MAAa,MAAM,QAAQ,MAAM,OAAO,CAAC,CAAC;CAC9E;;;;CAKA,AAAO,gBAAwB;EAC7B,OAAO,KAAK,OACT,YAAY,CAAC,CACb,MAAM,IAAI,CAAC,CACX,QAAQ,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC;CACnC;AACF"}
1
+ {"version":3,"file":"route-registry.mjs","names":[],"sources":["../../../../../../../core/src/router/route-registry.ts"],"sourcesContent":["import FindMyWay, { type HTTPMethod, type Instance } from \"find-my-way\";\nimport { normalizeRequestPath } from \"./normalize-request-path\";\nimport type { RequestMethod, Route } from \"./types\";\n\n/**\n * The concrete HTTP verbs an `all` route expands into.\n * Mirrors the set Fastify's `.all()` answers in production, so `router.any()`\n * routes behave identically under the dev server and prod Fastify.\n */\nconst ALL_METHODS: Exclude<RequestMethod, \"all\">[] = [\n \"GET\",\n \"POST\",\n \"PUT\",\n \"PATCH\",\n \"DELETE\",\n \"OPTIONS\",\n \"HEAD\",\n];\n\n/**\n * Route Registry\n * Manages dynamic route matching using find-my-way for HMR support\n */\nexport class RouteRegistry {\n private router: Instance<any>;\n\n public constructor() {\n this.router = FindMyWay({\n // Request paths are normalized explicitly in `find`; leaving this off\n // makes that shared normalizer, rather than a second router option, the\n // reason development accepts a terminal slash.\n ignoreTrailingSlash: false,\n caseSensitive: false,\n });\n }\n\n /**\n * Register all routes from the router's internal list\n */\n public register(routes: Route[]): void {\n // Register each route\n for (const route of routes) {\n if (route.method === \"all\") {\n for (const method of ALL_METHODS) {\n this.registerRoute({\n ...route,\n method,\n });\n }\n } else {\n this.registerRoute(route);\n }\n }\n }\n\n /**\n * Register a single route\n */\n public registerRoute(route: Route): void {\n this.router.on(route.method as HTTPMethod, route.path, (req, res, params) => {\n // Store the route and params for later use\n return { route, params };\n });\n }\n\n /**\n * Find a matching route for the given method and URL\n * @returns Matched route with extracted params, or null if no match\n */\n public find(\n method: string,\n url: string,\n ): { route: Route; params: Record<string, string> } | null {\n // Strip query string from URL (find-my-way expects just the path)\n const path = normalizeRequestPath(url.split(\"?\")[0] ?? \"/\");\n\n const match = this.router.find(method as HTTPMethod, path);\n\n if (!match) {\n return null;\n }\n\n // find-my-way handler expects (req, res, params, store, searchParams)\n // We only care about the return value which contains { route, params }\n return match.handler(null as any, null as any, match.params, match.store, {});\n }\n\n /**\n * Get all registered routes count (for debugging)\n */\n public getRouteCount(): number {\n return this.router\n .prettyPrint()\n .split(\"\\n\")\n .filter((line) => line.trim()).length;\n }\n}\n"],"mappings":";;;;;;;;;AASA,MAAM,cAA+C;CACnD;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;;;;AAMA,IAAa,gBAAb,MAA2B;CAGzB,AAAO,cAAc;EACnB,KAAK,SAAS,UAAU;GAItB,qBAAqB;GACrB,eAAe;EACjB,CAAC;CACH;;;;CAKA,AAAO,SAAS,QAAuB;EAErC,KAAK,MAAM,SAAS,QAClB,IAAI,MAAM,WAAW,OACnB,KAAK,MAAM,UAAU,aACnB,KAAK,cAAc;GACjB,GAAG;GACH;EACF,CAAC;OAGH,KAAK,cAAc,KAAK;CAG9B;;;;CAKA,AAAO,cAAc,OAAoB;EACvC,KAAK,OAAO,GAAG,MAAM,QAAsB,MAAM,OAAO,KAAK,KAAK,WAAW;GAE3E,OAAO;IAAE;IAAO;GAAO;EACzB,CAAC;CACH;;;;;CAMA,AAAO,KACL,QACA,KACyD;EAEzD,MAAM,OAAO,qBAAqB,IAAI,MAAM,GAAG,CAAC,CAAC,MAAM,GAAG;EAE1D,MAAM,QAAQ,KAAK,OAAO,KAAK,QAAsB,IAAI;EAEzD,IAAI,CAAC,OACH,OAAO;EAKT,OAAO,MAAM,QAAQ,MAAa,MAAa,MAAM,QAAQ,MAAM,OAAO,CAAC,CAAC;CAC9E;;;;CAKA,AAAO,gBAAwB;EAC7B,OAAO,KAAK,OACT,YAAY,CAAC,CACb,MAAM,IAAI,CAAC,CACX,QAAQ,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC;CACnC;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.mts","names":[],"sources":["../../../../../../../core/src/router/router.ts"],"mappings":"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"}
1
+ {"version":3,"file":"router.d.mts","names":[],"sources":["../../../../../../../core/src/router/router.ts"],"mappings":"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"}
@@ -11,7 +11,6 @@ import { RouteBuilder } from "./route-builder.mjs";
11
11
  import { log } from "@warlock.js/logger";
12
12
  import { isEmpty } from "@mongez/supportive-is";
13
13
  import { ltrim, merge, toCamelCase, trim } from "@mongez/reinforcements";
14
- import concatRoute from "@mongez/concat-route";
15
14
  import proxy from "@fastify/http-proxy";
16
15
  import fastifyStatic from "@fastify/static";
17
16
 
@@ -162,7 +161,7 @@ var Router = class Router {
162
161
  return this;
163
162
  }
164
163
  const prefix = this.stacks.prefix.reduce((path, prefix) => {
165
- return concatRoute(path, prefix);
164
+ return normalizeRoutePath(path, prefix);
166
165
  }, "");
167
166
  const name = this.stacks.name.reduceRight((name, prefixName) => {
168
167
  return trim(prefixName + "." + name, ".");