@warlock.js/core 5.17.1 → 5.19.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 (68) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/esm/container/development-model-modules.d.mts +22 -0
  3. package/esm/container/development-model-modules.d.mts.map +1 -0
  4. package/esm/container/index.d.mts +2 -0
  5. package/esm/container/index.d.mts.map +1 -1
  6. package/esm/container/index.mjs.map +1 -1
  7. package/esm/dev-server/model-module-registry.mjs +90 -0
  8. package/esm/dev-server/model-module-registry.mjs.map +1 -0
  9. package/esm/dev-server/module-loader.mjs +4 -0
  10. package/esm/dev-server/module-loader.mjs.map +1 -1
  11. package/esm/generations/add-command.action.mjs +9 -2
  12. package/esm/generations/add-command.action.mjs.map +1 -1
  13. package/esm/generations/pnpm-build-approvals.mjs +29 -0
  14. package/esm/generations/pnpm-build-approvals.mjs.map +1 -0
  15. package/esm/http/response.d.mts +3 -3
  16. package/esm/http/response.d.mts.map +1 -1
  17. package/esm/index.d.mts +3 -2
  18. package/esm/router/index.d.mts +1 -1
  19. package/esm/router/router.d.mts +8 -1
  20. package/esm/router/router.d.mts.map +1 -1
  21. package/esm/router/router.mjs +13 -0
  22. package/esm/router/router.mjs.map +1 -1
  23. package/esm/router/types.d.mts +7 -1
  24. package/esm/router/types.d.mts.map +1 -1
  25. package/llms-full.txt +54 -41
  26. package/llms.txt +41 -41
  27. package/package.json +11 -11
  28. package/skills/add-connector/SKILL.md +1 -1
  29. package/skills/benchmark-code/SKILL.md +1 -1
  30. package/skills/build-restful/SKILL.md +1 -1
  31. package/skills/build-url/SKILL.md +1 -1
  32. package/skills/configure-app/SKILL.md +1 -1
  33. package/skills/create-controller/SKILL.md +1 -1
  34. package/skills/create-module/SKILL.md +1 -1
  35. package/skills/define-resource/SKILL.md +1 -1
  36. package/skills/encrypt-data/SKILL.md +1 -1
  37. package/skills/hash-password/SKILL.md +1 -1
  38. package/skills/health-checks/SKILL.md +1 -1
  39. package/skills/lower-stage3-decorators/SKILL.md +1 -1
  40. package/skills/process-image/SKILL.md +1 -1
  41. package/skills/register-route/SKILL.md +14 -1
  42. package/skills/request-memo/SKILL.md +1 -1
  43. package/skills/request-tracing/SKILL.md +1 -1
  44. package/skills/resolve-path/SKILL.md +1 -1
  45. package/skills/retry-operation/SKILL.md +1 -1
  46. package/skills/run-app/SKILL.md +1 -1
  47. package/skills/send-mail/SKILL.md +1 -1
  48. package/skills/send-response/SKILL.md +1 -1
  49. package/skills/store-file/SKILL.md +1 -1
  50. package/skills/test-http/SKILL.md +1 -1
  51. package/skills/test-service/SKILL.md +1 -1
  52. package/skills/update-packages/SKILL.md +1 -1
  53. package/skills/upload-file/SKILL.md +1 -1
  54. package/skills/use-app-context/SKILL.md +1 -1
  55. package/skills/use-localization/SKILL.md +1 -1
  56. package/skills/use-middleware/SKILL.md +1 -1
  57. package/skills/use-model-transformers/SKILL.md +1 -1
  58. package/skills/use-repository/SKILL.md +1 -1
  59. package/skills/use-request-locals/SKILL.md +1 -1
  60. package/skills/validate-input/SKILL.md +1 -1
  61. package/skills/warlock-conventions/SKILL.md +1 -1
  62. package/skills/warlock-doctor/SKILL.md +1 -1
  63. package/skills/warlock-routes/SKILL.md +1 -1
  64. package/skills/wire-socket/SKILL.md +1 -1
  65. package/skills/write-cli-command/SKILL.md +1 -1
  66. package/skills/write-middleware/SKILL.md +1 -1
  67. package/skills/write-seeder/SKILL.md +1 -1
  68. package/skills/write-use-case/SKILL.md +1 -1
package/llms-full.txt CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  ---
10
10
  name: add-connector
11
- description: 'Extend Warlock with a `BaseConnector` subclass and register its instance in `warlock.config.ts > connectors`. Covers runtime lifecycle (`boot`, `start`, `shutdown`, priority, phase, watched files) and the optional static `build.generate` / `build.emit` contribution used by `warlock build`. Triggers: `BaseConnector`, `connectors`, `ConnectorLifecyclePhase`, `ConnectorBuildContribution`, `build.generate`, `build.emit`; "add a queue worker", "wire a subsystem into bootstrap", "contribute files to warlock build", "control startup ordering", "graceful shutdown hook". Skip: app context accessors — `@warlock.js/core/use-app-context/SKILL.md`; general config shape — `@warlock.js/core/configure-app/SKILL.md`; competing pattern: hand-rolled process signal blocks, NestJS lifecycle hooks.'
11
+ description: "Warlock — add a connector in @warlock.js/core; use when you need to add connector."
12
12
  ---
13
13
 
14
14
  # Warlock — add a connector
@@ -248,7 +248,7 @@ See the [Registering a connector](#registering-a-connector) section above for th
248
248
 
249
249
  ---
250
250
  name: benchmark-code
251
- description: 'Wrap a function with `measure(name, fn, options?)` to time it and classify the latency — onComplete/onError/onFinish hooks, `latencyRange` thresholds, `BenchmarkProfiler` for percentiles, `BenchmarkSnapshots` for raw captures. Triggers: `measure`, `BenchmarkProfiler`, `BenchmarkSnapshots`, `BenchmarkChannel`, `ConsoleChannel`, `latencyRange`, `shouldBenchmarkError`; "time this operation", "profile a slow service", "emit p50/p95/p99 metrics", "classify latency against thresholds"; typical import `import { measure, BenchmarkProfiler } from "@warlock.js/core"`. Skip: retry composition — `@warlock.js/core/retry-operation/SKILL.md`; benchmark config wiring — `@warlock.js/core/configure-app/SKILL.md`; competing libs `prom-client`, `pino`, `perf_hooks`, `console.time`.'
251
+ description: "Warlock — benchmark code in @warlock.js/core; use when you need to benchmark code."
252
252
  ---
253
253
 
254
254
  # Warlock — benchmark code
@@ -508,7 +508,7 @@ The `latency` is the *total* time including retries — useful for the SLO you a
508
508
 
509
509
  ---
510
510
  name: build-restful
511
- description: 'Generate standard CRUD endpoints — via `router.route(path).list().show().create().update().destroy()` chain or the `Restful` base class. Pick the chain by default; reach for `Restful` when you want repository-bound defaults. Triggers: `router.route`, `Restful`, `router.restfulResource`, `RouteResource`, `.crud`, `.nest`, `beforeCreate`, `onCreate`; "build a CRUD API", "register list/show/create/update/destroy", "repository-bound default handlers", "override a single REST action"; typical import `import { router, Restful } from "@warlock.js/core"`. Skip: wider router surface — `@warlock.js/core/register-route/SKILL.md`; per-action controllers — `@warlock.js/core/create-controller/SKILL.md`; wire mapping — `@warlock.js/core/define-resource/SKILL.md`; competing pattern: hand-rolled controllers, `@nestjs/swagger` decorator-driven CRUD.'
511
+ description: "Warlock — build a RESTful resource in @warlock.js/core; use when you need to build restful."
512
512
  ---
513
513
 
514
514
  # Warlock — build a RESTful resource
@@ -780,7 +780,7 @@ router.restfulResource("/orders", new OrdersRestful());
780
780
 
781
781
  ---
782
782
  name: build-url
783
- description: 'HTTP URL helpers — `url`, `publicUrl`, `assetsUrl`, `uploadsUrl`, anchored at `app.baseUrl`. Use to render `src` / `href` / API URLs in resources and responses. `setBaseUrl` is wired by the HTTP connector from `config.get("app.baseUrl")`. Triggers: `url`, `publicUrl`, `assetsUrl`, `uploadsUrl`, `setBaseUrl`, `BASE_URL`; "render an avatar src URL", "absolute download link", "embed asset URL in email", "URL helpers vs path helpers"; typical import `import { url, publicUrl, uploadsUrl } from "@warlock.js/core"`. Skip: filesystem paths — `@warlock.js/core/resolve-path/SKILL.md`; signed CDN URLs — `@warlock.js/core/store-file/SKILL.md`; resource output — `@warlock.js/core/define-resource/SKILL.md`; competing patterns: hand-rolled `${baseUrl}/...` template strings.'
783
+ description: "Warlock — build a URL in @warlock.js/core; use when you need to build url."
784
784
  ---
785
785
 
786
786
  # Warlock — build a URL
@@ -964,7 +964,7 @@ Don't call `setBaseUrl` per request — it's process-global and races every othe
964
964
 
965
965
  ---
966
966
  name: configure-app
967
- description: 'Configure a Warlock app — the two layers (`warlock.config.ts` for framework-level wiring, `src/config/*.ts` for subsystems), `.env` + `env()`, the `config()` getter for runtime reads, and `app.publicUrl`/`PUBLIC_APP_URL` (the app''s public origin). Triggers: `defineConfig`, `config.get`, `config.key`, `env`, `ConfigRegistry`, `HttpConfigurations`, `AppConfigurations`, `publicUrl`, `PUBLIC_APP_URL`, `getPublicUrl`; "add a new config file", "warlock.config.ts vs src/config", "read env values", "runtime config lookup", "app public origin/URL"; typical import `import { defineConfig, config, env } from "@warlock.js/core"`. Skip: cache driver registration — `@warlock.js/cache/cache-basics/SKILL.md`; mail config — `@warlock.js/core/send-mail/SKILL.md`; storage config — `@warlock.js/core/store-file/SKILL.md`; sitemap refusal on a missing origin — `@warlock.js/web/generate-sitemap/SKILL.md`; competing libs `dotenv` direct, `convict`, `node-config`.'
967
+ description: "Warlock — configure the app in @warlock.js/core; use when you need to configure app."
968
968
  ---
969
969
 
970
970
  # Warlock — configure the app
@@ -1268,7 +1268,7 @@ Internal `@warlock.js/*` packages read from `config.get("<name>")` the same way
1268
1268
 
1269
1269
  ---
1270
1270
  name: create-controller
1271
- description: 'Author HTTP controllers in @warlock.js/core — RequestHandler signature, validated input via seal schemas, response helpers, attaching metadata. Controllers are thin functions; business logic moves to services or use-cases. Triggers: `RequestHandler`, `Request<TSchema>`, `GuardedRequestHandler`, `request.validated`, `request.input`, `controller.validation`, `response.success`, `response.successCreate`; "write a controller", "attach a schema to a handler", "thin controller pattern", "guarded request type"; typical import `import { type RequestHandler } from "@warlock.js/core"`. Skip: response helper menu — `@warlock.js/core/send-response/SKILL.md`; schema authoring — `@warlock.js/core/validate-input/SKILL.md`; URL wiring — `@warlock.js/core/register-route/SKILL.md`; competing patterns: `express` middleware functions, `@nestjs/common` `@Controller`/`@Get` decorators.'
1271
+ description: "Warlock — create a controller in @warlock.js/core; use when you need to create controller."
1272
1272
  ---
1273
1273
 
1274
1274
  # Warlock — create a controller
@@ -1509,7 +1509,7 @@ No `if (!product)` branch in the controller. The error class carries the HTTP se
1509
1509
 
1510
1510
  ---
1511
1511
  name: create-module
1512
- description: 'Scaffold a new feature module under `src/app/<name>/` via `warlock generate.module` and the follow-up generators for controllers, models, repositories, resources, and validation schemas. Triggers: `warlock generate.module`, `generate.controller`, `generate.service`, `generate.model`, `generate.repository`, `generate.resource`, `generate.migration`, `--minimal`, `gen.m`; "scaffold a new module", "create CRUD bootstrap", "add a controller to a module", "generate a model"; typical CLI `npx warlock generate.module <name>`. Skip: framework-wide layout rules — `@warlock.js/core/warlock-conventions/SKILL.md`; routes file shape — `@warlock.js/core/register-route/SKILL.md`; controller shape — `@warlock.js/core/create-controller/SKILL.md`; competing tooling: `@nestjs/cli`, `hygen`, hand-rolled folder layouts.'
1512
+ description: "Warlock — create a module in @warlock.js/core; use when you need to create module."
1513
1513
  ---
1514
1514
 
1515
1515
  # Warlock — create a module
@@ -1703,7 +1703,7 @@ await warmupProductCache();
1703
1703
 
1704
1704
  ---
1705
1705
  name: define-resource
1706
- description: 'Map model fields to wire-shape via `defineResource()` or `Resource` subclasses. Output-only — never put business logic, hydration, or reconciliation in a resource. Triggers: `defineResource`, `Resource`, `RegisterResource`, `toJSON`, `"self"`, `"localized"`, `"uploadsUrl"`; "shape an API response", "nest related resources", "rename a field on output", "self-referential tree resource"; typical import `import { defineResource } from "@warlock.js/core"`. Skip: localized columns — `@warlock.js/core/use-localization/SKILL.md`; URL casting — `@warlock.js/core/build-url/SKILL.md`; controller side — `@warlock.js/core/create-controller/SKILL.md`; competing libs `@nestjs/swagger` `@ApiProperty`, `class-transformer`, hand-rolled DTO mappers.'
1706
+ description: "Warlock — define a resource in @warlock.js/core; use when you need to define resource."
1707
1707
  ---
1708
1708
 
1709
1709
  # Warlock — define a resource
@@ -2004,7 +2004,7 @@ export const CommentResource = defineResource({
2004
2004
 
2005
2005
  ---
2006
2006
  name: encrypt-data
2007
- description: 'Reversible AES-256-GCM `encrypt` / `decrypt` for secrets you need to read back; one-way HMAC-SHA256 `hmacHash` for deterministic fingerprints (lookup/dedup of encrypted columns). Keys come from `src/config/encryption.ts`. Triggers: `encrypt`, `decrypt`, `hmacHash`, `EncryptionConfigurations`, `APP_ENCRYPTION_KEY`, `APP_HMAC_KEY`; "store an API key reversibly", "fingerprint an encrypted column for lookup", "AES-256-GCM secret", "HMAC-SHA256 dedup key"; typical import `import { encrypt, decrypt, hmacHash } from "@warlock.js/core"`. Skip: password hashing — `@warlock.js/core/hash-password/SKILL.md`; config wiring — `@warlock.js/core/configure-app/SKILL.md`; competing libs Node `crypto` direct, `crypto-js`, `libsodium-wrappers`.'
2007
+ description: "Warlock — encrypt and fingerprint in @warlock.js/core; use when you need to encrypt data."
2008
2008
  ---
2009
2009
 
2010
2010
  # Warlock — encrypt and fingerprint
@@ -2216,7 +2216,7 @@ Password hashing (`hashPassword`) needs `bcryptjs`, which is its own install —
2216
2216
 
2217
2217
  ---
2218
2218
  name: hash-password
2219
- description: 'One-way bcrypt password hashing — `hashPassword` / `verifyPassword`, plus the declarative `useHashedPassword()` schema transformer that auto-hashes a model''s password field on save. Salt rounds come from `src/config/encryption.ts`. Triggers: `hashPassword`, `verifyPassword`, `useHashedPassword`, `password.salt`, `bcryptjs`; "hash a user password", "verify login credentials", "auto-hash on save", "rotate a password"; typical import `import { hashPassword, verifyPassword } from "@warlock.js/core"`. Skip: reversible secrets — `@warlock.js/core/encrypt-data/SKILL.md`; the other transformers — `@warlock.js/core/use-model-transformers/SKILL.md`; config wiring — `@warlock.js/core/configure-app/SKILL.md`; competing libs `bcrypt` native, `argon2`, `scrypt`.'
2219
+ description: "Warlock — hash a password in @warlock.js/core; use when you need to hash password."
2220
2220
  ---
2221
2221
 
2222
2222
  # Warlock — hash a password
@@ -2403,7 +2403,7 @@ There is no `warlock add` feature for password hashing — `bcryptjs` is a plain
2403
2403
 
2404
2404
  ---
2405
2405
  name: health-checks
2406
- description: 'Built-in liveness (`/health`) and readiness (`/ready`) endpoints plus graceful HTTP request draining for zero-downtime deploys — the `health` registry (`health.addCheck`/`removeCheck`), the `http.health.*` and `http.gracefulShutdown.*` config, and how readiness ties into `Application.isShuttingDown`. Triggers: `health`, `health.addCheck`, `health.removeCheck`, `HealthCheck`, `/health`, `/ready`, `http.health`, `http.gracefulShutdown`, `forceCloseConnections`, "liveness probe", "readiness probe", "graceful shutdown", "drain in-flight requests", "zero-downtime deploy", "kubernetes health check", "503 until ready"; typical import `import { health } from "@warlock.js/core"`. Skip: the `Application.onShutdown` / `onceBooted` lifecycle hooks — `@warlock.js/core/use-app-context/SKILL.md`; maintenance-mode 503s — `@warlock.js/core/use-middleware/SKILL.md`; connector lifecycle — `@warlock.js/core/add-connector/SKILL.md`; competing libs `@fastify/under-pressure`, `terminus`, hand-rolled `/health` controllers.'
2406
+ description: "Warlock — health checks & graceful shutdown in @warlock.js/core; use when you need to health checks."
2407
2407
  ---
2408
2408
 
2409
2409
  # Warlock — health checks & graceful shutdown
@@ -2526,7 +2526,7 @@ For an even smoother handoff, give the load balancer time to observe the 503 bef
2526
2526
 
2527
2527
  ---
2528
2528
  name: lower-stage3-decorators
2529
- description: 'Vite/Vitest plugin `lowerStage3Decorators()` that lowers TC39 Stage-3 (native) decorators with esbuild before oxc / the SSR rewrite mangles them — so `@RegisterModel`-decorated Cascade models load under Vitest 4 / Vite 8. Triggers: `lowerStage3Decorators`, "SyntaxError: Invalid or unexpected token" on a decorated class, "@(0, __vite_ssr_import__.X)()", "decorator crashes vitest", "models won''t load in tests", "Vite 8 oxc decorators"; typical import `import { lowerStage3Decorators } from "@warlock.js/core/vite"` in `vite.config.ts` / `vitest.config.ts`. Skip: writing the tests themselves — `@warlock.js/core/test-service/SKILL.md` / `@warlock.js/core/test-http/SKILL.md`; runtime migrations — `@warlock.js/cascade/write-migration/SKILL.md`.'
2529
+ description: "Lower Stage-3 decorators for Vite/Vitest in @warlock.js/core; use when you need to lower stage3 decorators."
2530
2530
  ---
2531
2531
 
2532
2532
  # Lower Stage-3 decorators for Vite/Vitest
@@ -2586,7 +2586,7 @@ It's the **same esbuild transform the production `tsx`/build path uses**, so a f
2586
2586
 
2587
2587
  ---
2588
2588
  name: process-image
2589
- description: 'Transform images with the `Image` class — resize, crop, rotate, format, quality, watermark, blur, etc. — using a deferred pipeline that runs only at `save()` / `toBuffer()` / `toBase64()` / `toDataUrl()` time. Requires sharp via `warlock add image`. Triggers: `Image`, `Image.fromFile`, `Image.fromBuffer`, `Image.fromUrl`, `.resize`, `.crop`, `.watermark`, `.toBuffer`, `.toDataUrl`, `.apply`; "resize an image", "generate a thumbnail", "watermark a product photo", "build an image pipeline"; typical import `import { Image } from "@warlock.js/core"`. Skip: multipart upload entry — `@warlock.js/core/upload-file/SKILL.md`; storage persistence — `@warlock.js/core/store-file/SKILL.md`; competing libs `sharp` direct, `jimp`, `imagemagick`, `gm`.'
2589
+ description: "Warlock — process an image in @warlock.js/core; use when you need to process image."
2590
2590
  ---
2591
2591
 
2592
2592
  # Warlock — process an image
@@ -2761,7 +2761,7 @@ See [`upload-file`](../upload-file/SKILL.md) for the multipart entry point and [
2761
2761
 
2762
2762
  ---
2763
2763
  name: register-route
2764
- description: 'Register HTTP routes via @warlock.js/core''s router — single routes, prefix groups, middleware-guarded blocks, and RESTful resource chains. Routes always live in `src/app/<module>/routes.ts`. Triggers: `router.get`, `router.post`, `router.prefix`, `router.group`, `router.route`, `guarded`; "add a route", "wire a controller to a URL", "group routes by prefix", "register a RESTful resource"; typical import `import { router } from "@warlock.js/core"`. Skip: handler shape — `@warlock.js/core/create-controller/SKILL.md`; CRUD chain details — `@warlock.js/core/build-restful/SKILL.md`; middleware authoring — `@warlock.js/core/write-middleware/SKILL.md`; competing libs `express`, `fastify`, `koa`, `@nestjs/common`.'
2764
+ description: "Warlock — register a route in @warlock.js/core; use when you need to register route."
2765
2765
  ---
2766
2766
 
2767
2767
  # Warlock — register a route
@@ -2777,6 +2777,19 @@ import { listProductsController } from "./controllers/list-products.controller";
2777
2777
  router.get("/products", listProductsController);
2778
2778
  ```
2779
2779
 
2780
+ ## Named API metadata for browser forms
2781
+
2782
+ Give a browser-submitted API route a stable `name`. Web publishes only its
2783
+ name, path, and method to `useSubmitForm`; controllers, middleware, schemas,
2784
+ and source paths never reach the browser.
2785
+
2786
+ ```ts
2787
+ router.post("/orders/:id", createOrderController, { name: "orders.create" });
2788
+ ```
2789
+
2790
+ Use a concrete HTTP verb for browser forms. `router.any()` is represented as
2791
+ `all` metadata and requires callers to choose an explicit path and method.
2792
+
2780
2793
  That's the entire contract for a simple route. `router` is a singleton; method calls register routes synchronously. The handler is a plain function (controllers are typed as `RequestHandler` — see [create-controller](../create-controller/SKILL.md)).
2781
2794
 
2782
2795
  ## HTTP verbs
@@ -2924,7 +2937,7 @@ router.get(["/health", "/healthz"], healthController);
2924
2937
 
2925
2938
  ---
2926
2939
  name: request-memo
2927
- description: 'Memoize async work for one HTTP request with `requestMemo<T>(key, fn)` — the v5 replacement for removed `fromRequest`, with single-flight promise sharing, settled-success reuse, rejection eviction, and no cross-request fallback. Triggers: `requestMemo`, `fromRequest`, `fromRequest removed`, `request-scoped cache`, `single-flight`, `current request memo`; "migrate off fromRequest", "load this once per request", "deduplicate concurrent loaders", "cache a repository lookup during one request"; typical import `import { requestMemo } from "@warlock.js/core"`. Skip: middleware-written request state — `@warlock.js/core/use-request-locals/SKILL.md`; process-wide or cross-request caching — `@warlock.js/core/use-middleware/SKILL.md`; competing patterns: dynamic `request[key]` properties, module-global `Map`, payload `request.get()` / `request.set()`.'
2940
+ description: "Warlock — memoize work for one request in @warlock.js/core; use when you need to request memo."
2928
2941
  ---
2929
2942
 
2930
2943
  # Warlock — memoize work for one request
@@ -3070,7 +3083,7 @@ Reusing one key for different result types is a caller bug: TypeScript cannot co
3070
3083
 
3071
3084
  ---
3072
3085
  name: request-tracing
3073
- description: 'Vendor-neutral request tracing hooks (`http.tracing`) — observe request start/end and named phase spans (`route.match`, `middleware`, `validation`, `handler`, `response.write`) without adopting an OTel/vendor dependency in `core`. Covers the `TracingHooks` shape, trace id derivation from an inbound W3C `traceparent` vs `request.id`, that a throwing hook is caught and reported once (never breaks the request), and zero overhead when disabled. Triggers: `http.tracing`, `TracingHooks`, `onRequestStart`, `onRequestEnd`, `onPhase`, `traceparent`, `traceId`, `dispatchPhase`, "instrument requests", "trace a request", "slow phase logging", "APM / OTel bridge for Warlock". Skip: request-id header echo/inheritance (`X-Request-Id`) — `@warlock.js/core/use-middleware/SKILL.md`; app-level structured logging — `@warlock.js/logger/logger-basics/SKILL.md`; competing libs `@opentelemetry/api` direct instrumentation, `express-request-id`, hand-rolled `X-Trace-Id` middleware.'
3086
+ description: "Warlock — request tracing hooks in @warlock.js/core; use when you need to request tracing."
3074
3087
  ---
3075
3088
 
3076
3089
  # Warlock — request tracing hooks
@@ -3282,7 +3295,7 @@ export default {
3282
3295
 
3283
3296
  ---
3284
3297
  name: resolve-path
3285
- description: 'Path helpers anchored at `process.cwd()` — `rootPath`, `srcPath`, `appPath`, `configPath`, `publicPath`, `storagePath`, `uploadsPath`, `cachePath`, `logsPath`, `tempPath`, `warlockPath`, `sanitizePath`. Optional `uploads.root` config overrides the uploads anchor. Triggers: `appPath`, `configPath`, `uploadsPath`, `storagePath`, `publicPath`, `cachePath`, `logsPath`, `tempPath`, `sanitizePath`, `paths`; "resolve a path inside src/app", "absolute upload destination", "sanitize a user filename", "ship uploads to a mounted volume"; typical import `import { appPath, uploadsPath } from "@warlock.js/core"`. Skip: HTTP URL helpers — `@warlock.js/core/build-url/SKILL.md`; app metadata — `@warlock.js/core/use-app-context/SKILL.md`; storage abstraction — `@warlock.js/core/store-file/SKILL.md`; competing patterns: `path.join(process.cwd(), ...)`, hand-rolled directory constants.'
3298
+ description: "Warlock — resolve a path in @warlock.js/core; use when you need to resolve path."
3286
3299
  ---
3287
3300
 
3288
3301
  # Warlock — resolve a path
@@ -3456,7 +3469,7 @@ If you find yourself reaching for `path.join(process.cwd(), ...)` — that's a s
3456
3469
 
3457
3470
  ---
3458
3471
  name: retry-operation
3459
- description: 'Wrap a flaky operation with `retry(fn, options)` — now provided by `@mongez/reinforcements` (not `@warlock.js/core`). `attempts` total tries, `delay` + `backoff` (linear/exponential/fn), `maxDelay`, `jitter`, `shouldRetry` to bail on permanent errors, `signal` to cancel, plus `retryable()` to pre-bind options. Triggers: `retry`, `retryable`, `RetryOptions`, `attempts`, `backoff`, `jitter`, `maxDelay`, `shouldRetry`, `signal`; "retry a flaky API call", "handle transient errors", "exponential backoff with jitter", "wrap an external request"; typical import `import { retry } from "@mongez/reinforcements"`. Skip: timing the retried op — `@warlock.js/core/benchmark-code/SKILL.md`; use-case-level `retry` option — `@warlock.js/core/write-use-case/SKILL.md`; competing libs `p-retry`, `async-retry`, `cockatiel`.'
3472
+ description: "Warlock — retry an operation in @warlock.js/core; use when you need to retry operation."
3460
3473
  ---
3461
3474
 
3462
3475
  # Warlock — retry an operation
@@ -3569,7 +3582,7 @@ const result = await measure("publish-event", () =>
3569
3582
 
3570
3583
  ---
3571
3584
  name: run-app
3572
- description: 'Three operational commands — `warlock dev` (HMR + type-gen + health checks), `warlock build` (esbuild bundle), `warlock start` (spawn the production bundle). All flags, all `warlock.config.ts` knobs that shape them. Triggers: `warlock dev`, `warlock build`, `warlock start`, `devServer`, `--fresh`, `--skip-typings`, `--skip-health`, `outdir`, `outFile`, `sourcemap`, `PortInUseError`, `assertPortIsAvailable`, `EADDRINUSE`, `EsbuildBinaryMissingError`; "start the dev server", "build for production", "run the bundle", "skip type generation", "tune watch globs", "dev server keyboard shortcuts", "press r to restart", "press q to quit", "restart the dev server", "port already in use"; typical config `warlock.config.ts > devServer / build`. Skip: writing a custom CLI — `@warlock.js/core/write-cli-command/SKILL.md`; config shape — `@warlock.js/core/configure-app/SKILL.md`; competing tooling `nodemon`, `tsx`, `ts-node-dev`, `esbuild` direct.'
3585
+ description: "Warlock — run the app in @warlock.js/core; use when you need to run app."
3573
3586
  ---
3574
3587
 
3575
3588
  # Warlock — run the app
@@ -4051,7 +4064,7 @@ NODE_OPTIONS=--max-old-space-size=4096 npx warlock start
4051
4064
 
4052
4065
  ---
4053
4066
  name: send-mail
4054
- description: 'Send transactional email — `Mail` fluent builder, `sendMail()` direct call, React Email components. Test mode auto-captures into an in-memory mailbox; dev mode logs. Triggers: `Mail.to`, `sendMail`, `setMailMode`, `mailEvents`, `assertMailSent`, `getTestMailbox`, `wasMailSentTo`, `closeAllMailers`; "send a transactional email", "build a React Email template", "configure SMTP or SES", "assert an email was sent in tests"; typical import `import { Mail, sendMail } from "@warlock.js/core"`. Skip: per-config wiring — `@warlock.js/core/configure-app/SKILL.md`; layered service patterns — `@warlock.js/core/warlock-conventions/SKILL.md`; competing libs `nodemailer` direct, `@sendgrid/mail`, `resend`, `mailgun.js`.'
4067
+ description: "Warlock — send a mail in @warlock.js/core; use when you need to send mail."
4055
4068
  ---
4056
4069
 
4057
4070
  # Warlock — send a mail
@@ -4427,7 +4440,7 @@ await Mail.to(user.email)
4427
4440
 
4428
4441
  ---
4429
4442
  name: send-response
4430
- description: 'Send HTTP responses via @warlock.js/core''s Response helpers — success/error variants, status helpers, redirects, files, streams, and SSE. Picking the right helper carries the HTTP semantic without manual status codes. Triggers: `response.success`, `response.successCreate`, `response.notFound`, `response.forbidden`, `response.badRequest`, `response.sendFile`, `response.stream`, `response.sse`, `response.replay`, `ResourceNotFoundError`, `ForbiddenError`, `request.cookie`, `request.hasCookie`, `CookieJarUnavailableError`; "return a 201 from a controller", "send a file", "stream Server-Sent Events", "throw HTTP-shaped errors from services"; typical import `import type { RequestHandler, Response } from "@warlock.js/core"`. Skip: controller shape — `@warlock.js/core/create-controller/SKILL.md`; route registration — `@warlock.js/core/register-route/SKILL.md`; competing patterns: hand-rolled status codes via `reply.code(404).send(...)`, raw Fastify reply.'
4443
+ description: "Warlock — send a response in @warlock.js/core; use when you need to send response."
4431
4444
  ---
4432
4445
 
4433
4446
  # Warlock — send a response
@@ -4741,7 +4754,7 @@ return response.header("X-Cache", "HIT").replay({
4741
4754
 
4742
4755
  ---
4743
4756
  name: store-file
4744
- description: 'Read/write/delete files via the `storage` singleton — disks, drivers (local/S3/R2/DO Spaces), `storage.use(name)`, `StorageFile` handles, presigned URLs. Triggers: `storage.put`, `storage.get`, `storage.use`, `StorageFile`, `storageConfigurations`, `getPresignedUrl`, `getPresignedUploadUrl`; "save an uploaded file", "switch between local and S3", "generate a presigned URL", "read file metadata"; typical import `import { storage } from "@warlock.js/core"`. Skip: multipart parsing + image chain — `@warlock.js/core/upload-file/SKILL.md`; image transforms — `@warlock.js/core/process-image/SKILL.md`; storage config shape — `@warlock.js/core/configure-app/SKILL.md`; competing libs `@aws-sdk/client-s3`, `multer`, `formidable`.'
4757
+ description: "Warlock — store a file in @warlock.js/core; use when you need to store file."
4745
4758
  ---
4746
4759
 
4747
4760
  # Warlock — store a file
@@ -5135,7 +5148,7 @@ Client `PUT`s the bytes straight to R2 — your server never sees them.
5135
5148
 
5136
5149
  ---
5137
5150
  name: test-http
5138
- description: 'Integration tests against a real HTTP server — `startHttpTestServer()` boots one shared server in globalSetup, then `testGet` / `testPost` / `expectJson` make typed requests against it. Triggers: `startHttpTestServer`, `startHttpTestServer({ port })`, `stopHttpTestServer`, `testGet`, `testPost`, `testPut`, `testPatch`, `testDelete`, `expectJson`, `getTestServerUrl`, `testRequest`, `PortInUseError`, `assertPortIsAvailable`, `isPortAvailable`; "integration-test a controller", "end-to-end HTTP test", "globalSetup HTTP server", "assert status and body shape", "test server port already in use", "EADDRINUSE while running tests", "run tests while the dev server is up"; typical import `import { testGet, testPost, expectJson } from "@warlock.js/core/tests"`. Skip: pure unit tests — `@warlock.js/core/test-service/SKILL.md`; controller shape — `@warlock.js/core/create-controller/SKILL.md`; competing libs `supertest`, `light-my-request`, `nock`.'
5151
+ description: "Warlock — HTTP integration tests in @warlock.js/core; use when you need to test http."
5139
5152
  ---
5140
5153
 
5141
5154
  # Warlock — HTTP integration tests
@@ -5476,7 +5489,7 @@ This is fine for normal test flow. It bites when you're inside a transaction the
5476
5489
 
5477
5490
  ---
5478
5491
  name: test-service
5479
- description: 'Pure unit tests against services, repositories, models, and use-cases — `setupTest({ connectors })` bootstraps the framework with its own DB/cache connections so you can call your code directly, and `teardownTest()` closes it. Triggers: `setupTest`, `teardownTest`, `src/test-setup.ts`, `tests.connectors`, `tests.setupTimeout`, `Application.setEnvironment`; "unit-test a service", "test a repository query", "vitest setupFiles", "skip connectors for pure-logic tests"; typical import `import { setupTest, teardownTest } from "@warlock.js/core/tests"`. Skip: HTTP integration — `@warlock.js/core/test-http/SKILL.md`; warlock add test scaffold — `@warlock.js/core/write-cli-command/SKILL.md`; competing tooling: jest direct, `supertest`, `nock`.'
5492
+ description: "Warlock — test a service in @warlock.js/core; use when you need to test service."
5480
5493
  ---
5481
5494
 
5482
5495
  # Warlock — test a service
@@ -5865,7 +5878,7 @@ In both cases the guard's scope matches the resource's scope, which is the point
5865
5878
 
5866
5879
  ---
5867
5880
  name: update-packages
5868
- description: 'Keep a project current with `warlock update` — bump every `@warlock.js/*` dependency in package.json to its latest published version (range operator preserved), then run the lockfile-detected package manager install. Also covers the `warlock dev` update notice, its `u` update-and-restart keyboard shortcut, and the `devServer.checkForUpdates` toggle. Triggers: `warlock update`, `--no-install`, `--dry-run`, `--check`, `checkForUpdates`, `fetchLatestVersion`, `isNewerVersion`; "update warlock packages", "upgrade the framework", "is there a new warlock version", "update notice in the dev server", "press u to update", "dev server keyboard shortcut", "update check offline", "bump @warlock.js/* to latest"; typical CLI `warlock update`. Skip: dev/build/start runtime — `@warlock.js/core/run-app/SKILL.md`; writing a custom command — `@warlock.js/core/write-cli-command/SKILL.md`; installing a NEW feature package (auth, mail, storage) — that is `warlock add`; releasing/publishing the framework — workspace release tooling, not this command.'
5881
+ description: "Warlock — update the framework in @warlock.js/core; use when you need to update packages."
5869
5882
  ---
5870
5883
 
5871
5884
  # Warlock — update the framework
@@ -6002,7 +6015,7 @@ Two small zero-dependency utilities back the tooling and are exported from `@war
6002
6015
 
6003
6016
  ---
6004
6017
  name: upload-file
6005
- description: 'Handle multipart file uploads — read via `request.file()` or `request.validated()`, validate with `v.file()`, save via `UploadedFile.save()` or the storage layer, transform images inline. Triggers: `UploadedFile`, `request.file`, `v.file`, `.save`, `.saveAs`, `.resize`, `.format`, `.quality`, `.image`, `.mimeType`, `.maxSize`; "accept a file upload", "validate file size and mime", "save to S3 or local disk", "resize an uploaded image on save"; typical import `import type { UploadedFile, RequestHandler } from "@warlock.js/core"`. Skip: storage drivers + presigned URLs — `@warlock.js/core/store-file/SKILL.md`; image-only transforms — `@warlock.js/core/process-image/SKILL.md`; schema rules — `@warlock.js/core/validate-input/SKILL.md`; competing libs `multer`, `formidable`, `busboy`.'
6018
+ description: "Warlock — upload a file in @warlock.js/core; use when you need to upload file."
6006
6019
  ---
6007
6020
 
6008
6021
  # Warlock — upload a file
@@ -6317,7 +6330,7 @@ The reverse direction — sending a stored file back via `response.sendFile(...)
6317
6330
 
6318
6331
  ---
6319
6332
  name: use-app-context
6320
- description: 'Read app-wide context — the `Application` static class (env, version, uptime, runtime strategy, boot lifecycle) plus the `app` runtime accessor (live Fastify, socket.io, router, database via the DI container). Triggers: `Application.isProduction`, `Application.environment`, `Application.runtimeStrategy`, `Application.uptime`, `Application.version`, `Application.onceBooted`, `Application.whenBooted`, `Application.isBooted`, `Application.onShutdown`, `Application.isShuttingDown`, `app.http`, `app.socket`, `app.database`, `app.router`; "branch on environment", "reach the live Fastify instance", "framework version in health endpoint", "dev vs production runtime check", "run code once the app is fully booted", "after all connectors started", "app booted hook", "run cleanup before shutdown", "graceful shutdown hook"; typical import `import { Application, app } from "@warlock.js/core"`. Skip: path helpers — `@warlock.js/core/resolve-path/SKILL.md`; connector start order — `@warlock.js/core/add-connector/SKILL.md`; competing patterns: bare `process.env.NODE_ENV`, ad-hoc Fastify imports.'
6333
+ description: "Warlock — use the application context in @warlock.js/core; use when you need to use app context."
6321
6334
  ---
6322
6335
 
6323
6336
  # Warlock — use the application context
@@ -6621,7 +6634,7 @@ cors: {
6621
6634
 
6622
6635
  ---
6623
6636
  name: use-localization
6624
- description: 'Multi-locale translations via `groupedTranslations` (declare keys), `t()` / `request.t()` / `request.trans()` (look up), `request.getLocaleCode()` (detect locale from headers/query), `getLocalized` (pick the right value from a localized-array column). Triggers: `groupedTranslations`, `t`, `request.t`, `request.trans`, `request.transFrom`, `request.getLocaleCode`, `request.setLocaleCode`, `getLocalized`; "add a translation key", "resolve a localized error message", "detect request locale", "pick the right per-locale column value"; typical import `import { t, getLocalized } from "@warlock.js/core"`. Skip: resource output — `@warlock.js/core/define-resource/SKILL.md`; module scaffold — `@warlock.js/core/create-module/SKILL.md`; competing libs `i18next`, `react-intl`, raw `@mongez/localization`.'
6637
+ description: "Warlock — translate keys + pick localized values in @warlock.js/core; use when you need to use localization."
6625
6638
  ---
6626
6639
 
6627
6640
  # Warlock — translate keys + pick localized values
@@ -6950,7 +6963,7 @@ When a route-locales snapshot applies, `request.t()`, `request.trans()`, and `re
6950
6963
 
6951
6964
  ---
6952
6965
  name: use-middleware
6953
- description: 'Attach built-in HTTP middleware to routes via the `middleware` namespace from `@warlock.js/core` — rateLimit, concurrencyLimit, maxBodySize, idempotency, maintenance, ipFilter, cache. Plus `X-Request-Id` correlation, wired automatically. Triggers: `middleware.rateLimit`, `middleware.concurrencyLimit`, `middleware.maxBodySize`, `middleware.idempotency`, `middleware.maintenance`, `middleware.ipFilter`, `middleware.cache`, `X-Request-Id`, `Idempotency-Key`; "add rate limiting", "dedupe writes by idempotency key", "cap concurrent requests", "block IPs", "cache a GET response"; typical import `import { middleware } from "@warlock.js/core"`. Skip: author custom middleware — `@warlock.js/core/write-middleware/SKILL.md`; cache singleton — `@warlock.js/cache/cache-basics/SKILL.md`; competing libs `@fastify/rate-limit` direct, `express-rate-limit`, `helmet`.'
6966
+ description: "Warlock — use built-in middleware in @warlock.js/core; use when you need to use middleware."
6954
6967
  ---
6955
6968
 
6956
6969
  # Warlock — use built-in middleware
@@ -7223,7 +7236,7 @@ export default {
7223
7236
 
7224
7237
  ---
7225
7238
  name: use-model-transformers
7226
- description: 'Three schema-side helpers — `useHashedPassword()` (bcrypt on save) attaches via `.addTransformer(...)`; `useComputedSlug(field?, scope?)` (auto-slug from another field) and `useComputedModel(callback)` (arbitrary computed-on-save value) attach via `v.computed(...)`. Triggers: `useHashedPassword`, `useComputedSlug`, `useComputedModel`, `.addTransformer`, `v.computed`, `ComputedCallback`; "auto-hash a password field", "auto-slug from title on save", "derive a value at write time", "declarative model transformers"; typical import `import { useHashedPassword, useComputedSlug } from "@warlock.js/core"`. Skip: bcrypt setup details — `@warlock.js/core/hash-password/SKILL.md`; repository writes — `@warlock.js/core/use-repository/SKILL.md`; output filtering — `@warlock.js/core/define-resource/SKILL.md`; competing patterns: manual `await hashPassword(input)` in services, ORM lifecycle hooks.'
7239
+ description: "Warlock — declare model transformers in @warlock.js/core; use when you need to use model transformers."
7227
7240
  ---
7228
7241
 
7229
7242
  # Warlock — declare model transformers
@@ -7447,7 +7460,7 @@ Rule of thumb: transformers are for **pure, deterministic** transforms of the ro
7447
7460
 
7448
7461
  ---
7449
7462
  name: use-repository
7450
- description: 'Subclass `RepositoryManager` for data access — declare `source`, `filterBy`, `defaultOptions`, then call `list()`/`listCached()`/`find()`/`create()`/`update()`/`delete()`, the active/cached/cursor variants, and the `filterBy`-aware aggregates `sum()`/`avg()`/`min()`/`max()`/`groupBy()`/`aggregate()`. Triggers: `RepositoryManager`, `FilterRules`, `RepositoryOptions`, `.list`, `.listCached`, `.find`, `.findCached`, `.create`, `.update`, `.delete`, `.sum`, `.avg`, `.min`, `.max`, `.groupBy`, `.aggregate`, `simpleSelectColumns`; "create a repository", "filter rules for a list endpoint", "cursor vs page pagination", "cached vs uncached read", "sum/avg/group-by with filters"; typical import `import { RepositoryManager } from "@warlock.js/core"`. Skip: cache singleton — `@warlock.js/cache/cache-basics/SKILL.md`; use-case pipelines — `@warlock.js/core/write-use-case/SKILL.md`; wire mapping — `@warlock.js/core/define-resource/SKILL.md`; competing libs `typeorm` Repository, `prisma.client.<model>`, `@nestjs/typeorm`.'
7463
+ description: "Warlock — use a repository in @warlock.js/core; use when you need to use repository."
7451
7464
  ---
7452
7465
 
7453
7466
  # Warlock — use a repository
@@ -7881,7 +7894,7 @@ The third arg is a context object — `{ allValues, dateFormat, ... }` — for f
7881
7894
 
7882
7895
  ---
7883
7896
  name: use-request-locals
7884
- description: 'Carry typed, server-only data through one HTTP request with `request.locals`, usually written by middleware and read by downstream middleware or controllers. Augment `RequestLocals` in the module that owns each key; v5 no longer permits arbitrary `request.foo` properties. Triggers: `request.locals`, `RequestLocals`, `request.post`, `request.organization`, `Property does not exist on type Request`, `Request index signature`; "attach data to a request", "share middleware data with a controller", "type request locals", "migrate dynamic request properties"; typical type augmentation `declare module "@warlock.js/core" { interface RequestLocals { ... } }`. Skip: computed-on-demand single-flight values and removed `fromRequest` — `@warlock.js/core/request-memo/SKILL.md`; middleware mechanics — `@warlock.js/core/write-middleware/SKILL.md`; authenticated user typing — augment `RequestUser`, not `RequestLocals`; competing patterns: `(request as any).foo`, `request.set()`, module-global mutable state.'
7897
+ description: "Warlock — use typed request locals in @warlock.js/core; use when you need to use request locals."
7885
7898
  ---
7886
7899
 
7887
7900
  # Warlock — use typed request locals
@@ -8052,7 +8065,7 @@ Writing `request.locals.organization` does not affect `request.all()`, `request.
8052
8065
 
8053
8066
  ---
8054
8067
  name: validate-input
8055
- description: 'Author seal schemas, attach them to controllers via `controller.validation = { schema }`, infer types via `Infer<typeof schema>`, and layer DB-aware (`unique`/`exists`) and file validators on top. Triggers: `v.object`, `v.string`, `v.email`, `Infer`, `controller.validation`, `.unique`, `.exists`, `uniqueExceptCurrentId`, `request.validated`; "validate a request body", "attach a schema to a controller", "DB-aware unique rule", "infer schema types"; typical import `import { v, type Infer } from "@warlock.js/seal"`. Skip: schema authoring foundations — `@warlock.js/seal/seal-basics/SKILL.md`; controller wiring — `@warlock.js/core/create-controller/SKILL.md`; file rules deep-dive — `@warlock.js/core/upload-file/SKILL.md`; competing libs `zod`, `joi`, `yup`, `class-validator`.'
8068
+ description: "Warlock — validate a request in @warlock.js/core; use when you need to validate input."
8056
8069
  ---
8057
8070
 
8058
8071
  # Warlock — validate a request
@@ -8366,7 +8379,7 @@ updateProductController.validation = {
8366
8379
 
8367
8380
  ---
8368
8381
  name: warlock-conventions
8369
- description: 'Framework-wide invariants for projects built on @warlock.js/core — module layout, canonical imports, layered flow, file naming, and the non-negotiable rules every other warlock skill assumes. Triggers: `src/app/<module>`, `routes.ts`, `main.ts`, `Request<TSchema>`, `RequestHandler`, `GuardedRequestHandler`, `app/<module>/...`; "where do files go in this project", "canonical Warlock imports", "module layout rules", "controller-service-repository layering"; typical import `import { router, type RequestHandler } from "@warlock.js/core"`. Skip: scaffold a new module — `@warlock.js/core/create-module/SKILL.md`; route shape — `@warlock.js/core/register-route/SKILL.md`; controller shape — `@warlock.js/core/create-controller/SKILL.md`; competing patterns: `express` ad-hoc layouts, `@nestjs/common` decorator-driven structure.'
8382
+ description: "Warlock — framework-wide conventions in @warlock.js/core; use when you need to warlock conventions."
8370
8383
  ---
8371
8384
 
8372
8385
  # Warlock — framework-wide conventions
@@ -8499,7 +8512,7 @@ Cascade uses `@RegisterModel()` for the model registry and `@BelongsTo` / `@HasM
8499
8512
 
8500
8513
  ---
8501
8514
  name: warlock-doctor
8502
- description: 'Run `warlock doctor` — a read-only diagnostics command that checks routes / config / connectors / optional-peers / health endpoints / release hygiene and prints a pass/warn/fail report, exiting non-zero on any failure. Add your own probe with the `DoctorCheck` contract and `runChecks` / `formatReportLines`. Triggers: `warlock doctor`, `doctorCommand`, `DoctorCheck`, `CheckResult`, `CheckStatus`, `DoctorReport`, `runChecks`, `formatReportLines`, `printReport`, `defaultDoctorChecks`; "diagnose my app", "preflight / preflight check", "is the app healthy", "why are there 0 routes", "pre-release sanity check", "CI smoke check"; run as `npx warlock doctor`. Skip: the live `/health` + `/ready` HTTP probes — `@warlock.js/core/health-checks/SKILL.md`; authoring a general CLI command — `@warlock.js/core/write-cli-command/SKILL.md`; releasing the package — `releasing-warlock-monorepo`; competing tools `npm doctor`, `nest info`, hand-rolled preflight scripts.'
8515
+ description: "Warlock — warlock doctor in @warlock.js/core; use when you need to warlock doctor."
8503
8516
  ---
8504
8517
 
8505
8518
  # Warlock — `warlock doctor`
@@ -8641,7 +8654,7 @@ A `⚠ routes: 0 routes registered` line is the tell that a route module threw o
8641
8654
 
8642
8655
  ---
8643
8656
  name: warlock-routes
8644
- description: 'Run `warlock routes` — a read-only command that lists the registered HTTP routes as a verb-colored table (method / path / name / action / middleware-count / source), a sibling of `warlock doctor`. Filter with `--method` / `--path` / `--name`, or emit normalized rows as JSON with `--json`. Also covers `warlock routes:diff`, which compares live page routes against the last `warlock build`''s route snapshot and exits non-zero on drift. Triggers: `warlock routes`, `routesCommand`, `warlock routes:diff`, `routesDiffCommand`, "list my routes", "show all routes", "route table", "what endpoints does my app expose", "dump routes as JSON", "which routes have middleware", "route map for CI", "did my page routes drift from the last build"; run as `npx warlock routes` / `npx warlock routes:diff`. Skip: read-only health/preflight checks — `@warlock.js/core/warlock-doctor/SKILL.md`; defining/naming/grouping routes — `@warlock.js/core/register-route/SKILL.md`; authoring a general CLI command — `@warlock.js/core/write-cli-command/SKILL.md`; competing tools `nest`/`express` route listers, `php artisan route:list`.'
8657
+ description: "Warlock — warlock routes in @warlock.js/core; use when you need to warlock routes."
8645
8658
  ---
8646
8659
 
8647
8660
  # Warlock — `warlock routes`
@@ -8774,7 +8787,7 @@ and exits non-zero.
8774
8787
 
8775
8788
  ---
8776
8789
  name: wire-socket
8777
- description: 'Configure Socket.IO via `src/config/socket.ts`, reach the live server through `getSocketServer()` (or `app.socket` post-bootstrap), register `connection` handlers once the late-phase socket connector has booted, emit from controllers/services, use rooms and namespaces. Triggers: `app.socket`, `getSocketServer`, `SocketOptions`, `socket.io` `Server`, `socket.join`, `socket.to`, `io.of`, `io.use`; "add realtime chat", "emit socket events from a service", "use rooms and namespaces", "per-socket JWT auth". Skip: connector lifecycle — `@warlock.js/core/add-connector/SKILL.md`; app context accessors — `@warlock.js/core/use-app-context/SKILL.md`; competing libs `ws`, `socket.io` direct without Warlock connector, `uWebSockets.js`.'
8790
+ description: "Warlock — wire a Socket.IO server in @warlock.js/core; use when you need to wire socket."
8778
8791
  ---
8779
8792
 
8780
8793
  # Warlock — wire a Socket.IO server
@@ -9062,7 +9075,7 @@ CLI commands, scheduled jobs, queue workers — anything running outside an HTTP
9062
9075
 
9063
9076
  ---
9064
9077
  name: write-cli-command
9065
- description: 'Author a custom `warlock <my-cmd>` command via the `command()` factory — name, description, action, options, preload, then register in `warlock.config.ts > cli.commands` or drop in `src/app/<module>/commands/`. Also covers built-in `warlock add` feature scaffolding, including the Web starter and `index.register.ts`. Triggers: `command`, `CLICommand`, `CLICommandPreload`, `CLICommandOption`, `preload`, `preAction`, `persistent`, `colors`, `warlock add`, `warlock add bull-board`, `index.register.ts`; "write a custom warlock command", "one-off maintenance task", "ship a CLI from a package", "framework built-in commands"; typical import `import { command } from "@warlock.js/core"`. Skip: framework dev/build/start — `@warlock.js/core/run-app/SKILL.md`; warlock.config.ts wiring — `@warlock.js/core/configure-app/SKILL.md`; competing libs `commander`, `yargs`, `oclif`.'
9078
+ description: "Warlock — write a CLI command in @warlock.js/core; use when you need to write cli command."
9066
9079
  ---
9067
9080
 
9068
9081
  # Warlock — write a CLI command
@@ -9377,7 +9390,7 @@ export default command({
9377
9390
 
9378
9391
  ---
9379
9392
  name: write-middleware
9380
- description: 'Author HTTP middleware for @warlock.js/core — the `({ request, response })` signature, short-circuit by returning a response, enrich the request with extra fields, register per-route, per-group, or app-wide. Triggers: `Middleware`, `MiddlewareResponse`, `router.group`, `guarded`, `request.detectIp`, `authMiddleware`; "write a custom middleware", "short-circuit a request", "enrich the request with extra fields", "per-route vs per-group middleware"; typical import `import type { Middleware } from "@warlock.js/core"`. Skip: built-in middleware catalog — `@warlock.js/core/use-middleware/SKILL.md`; route attachment — `@warlock.js/core/register-route/SKILL.md`; response helpers — `@warlock.js/core/send-response/SKILL.md`; competing patterns: `express` `(req, res, next)` middleware, Fastify `preHandler` hooks.'
9393
+ description: "Warlock — write a middleware in @warlock.js/core; use when you need to write middleware."
9381
9394
  ---
9382
9395
 
9383
9396
  # Warlock — write a middleware
@@ -9605,7 +9618,7 @@ export const optionalAuth: Middleware = async ({ request, response }) => {
9605
9618
 
9606
9619
  ---
9607
9620
  name: write-seeder
9608
- description: 'Author a seed file under `src/app/<module>/seeds/<name>.ts` using the `seeder()` factory — `name`, `dependsOn`, `once`, `order`, `batchSize`, `run({ track, now, batchSize })`. Auto-discovered by `warlock seed`; tracked in a `seeds` table; per-record refs in `seed_records` so `warlock seed --drop` can undo a seed. Triggers: `seeder`, `Seeder`, `SeedResult`, `SeedContext`, `SeedClock`, `track`, `now`, `batchSize`, `SeedersManager`, `warlock seed`, `--fresh`, `--drop`, `--list`, `--path`; "seed default roles", "undo a seed", "one-time data migration", "auto-discovered seeds", "order seeds by dependency", "deterministic seed timestamps", "inject a seed clock"; typical import `import { seeder } from "@warlock.js/core"`. Skip: module folder layout — `@warlock.js/core/create-module/SKILL.md`; repository CRUD — `@warlock.js/core/use-repository/SKILL.md`; CLI flags — `@warlock.js/core/write-cli-command/SKILL.md`; competing patterns: hand-rolled `node scripts/seed.js`, `typeorm-seeding`.'
9621
+ description: "Warlock — write a seeder in @warlock.js/core; use when you need to write seeder."
9609
9622
  ---
9610
9623
 
9611
9624
  # Warlock — write a seeder
@@ -9986,7 +9999,7 @@ warlock seed --transaction # (default true) — pass --transaction=false to s
9986
9999
 
9987
10000
  ---
9988
10001
  name: write-use-case
9989
- description: 'Author `useCase()` pipelines for business logic — guards, schema, before/after middleware, retry, benchmark, broadcast, lifecycle callbacks; transport-agnostic and observable by default. Input is inferred from the `schema`. Triggers: `useCase`, `UseCaseContext`, `UseCaseResult`, `retry`, `benchmark`, `broadcast`, `description`, `globalUseCasesEvents`, `UseCaseBroadcastChannel`; "encapsulate a business operation", "share logic between HTTP and CLI", "add guards and lifecycle hooks", "broadcast a use case result", "transport-agnostic pipeline"; typical import `import { useCase } from "@warlock.js/core"`. Skip: thin handler shape — `@warlock.js/core/create-controller/SKILL.md`; schema details — `@warlock.js/core/validate-input/SKILL.md`; the standalone retry util — `@warlock.js/core/retry-operation/SKILL.md`; competing libs `@nestjs/cqrs`, `inversify`, hand-rolled service classes.'
10002
+ description: "Warlock — write a use case in @warlock.js/core; use when you need to write use case."
9990
10003
  ---
9991
10004
 
9992
10005
  # Warlock — write a use case