@warlock.js/core 5.28.0 → 5.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/esm/container/development-app-modules.d.mts +31 -0
- package/esm/container/development-app-modules.d.mts.map +1 -0
- package/esm/container/index.d.mts +2 -0
- package/esm/container/index.d.mts.map +1 -1
- package/esm/container/index.mjs.map +1 -1
- package/esm/dev-server/app-module-registry.mjs +52 -0
- package/esm/dev-server/app-module-registry.mjs.map +1 -0
- package/esm/dev-server/files-orchestrator.mjs +13 -2
- package/esm/dev-server/files-orchestrator.mjs.map +1 -1
- package/esm/index.d.mts +3 -1
- package/esm/index.mjs +2 -1
- package/esm/localization/parse-locale-dictionary.d.mts +6 -1
- package/esm/localization/parse-locale-dictionary.d.mts.map +1 -1
- package/esm/localization/parse-locale-dictionary.mjs +5 -1
- package/esm/localization/parse-locale-dictionary.mjs.map +1 -1
- package/esm/openapi/response-schemas.mjs +4 -1
- package/esm/openapi/response-schemas.mjs.map +1 -1
- package/esm/openapi/schema-registry.mjs +6 -0
- package/esm/openapi/schema-registry.mjs.map +1 -1
- package/esm/resource/index.d.mts +1 -0
- package/esm/resource/index.mjs +1 -0
- package/esm/resource/nullable-resource.d.mts +44 -0
- package/esm/resource/nullable-resource.d.mts.map +1 -0
- package/esm/resource/nullable-resource.mjs +38 -0
- package/esm/resource/nullable-resource.mjs.map +1 -0
- package/esm/resource/resource.d.mts.map +1 -1
- package/esm/resource/resource.mjs +22 -3
- package/esm/resource/resource.mjs.map +1 -1
- package/esm/resource/types.d.mts +10 -5
- package/esm/resource/types.d.mts.map +1 -1
- package/esm/router/response-schema-types.mjs +2 -0
- package/esm/router/response-schema-types.mjs.map +1 -1
- package/llms-full.txt +241 -241
- package/llms.txt +42 -42
- package/package.json +12 -12
- package/skills/README.md +39 -39
- package/skills/add-connector/SKILL.md +4 -4
- package/skills/benchmark-code/SKILL.md +3 -3
- package/skills/build-restful/SKILL.md +5 -5
- package/skills/build-url/SKILL.md +7 -7
- package/skills/configure-app/SKILL.md +7 -7
- package/skills/create-controller/SKILL.md +8 -8
- package/skills/create-module/SKILL.md +9 -9
- package/skills/define-resource/SKILL.md +4 -4
- package/skills/encrypt-data/SKILL.md +7 -7
- package/skills/generate-openapi/SKILL.md +5 -5
- package/skills/hash-password/SKILL.md +8 -8
- package/skills/health-checks/SKILL.md +6 -6
- package/skills/lower-stage3-decorators/SKILL.md +4 -4
- package/skills/process-image/SKILL.md +5 -5
- package/skills/register-route/SKILL.md +6 -6
- package/skills/request-memo/SKILL.md +4 -4
- package/skills/request-tracing/SKILL.md +6 -6
- package/skills/resolve-path/SKILL.md +6 -6
- package/skills/retry-operation/SKILL.md +4 -4
- package/skills/run-app/SKILL.md +11 -11
- package/skills/send-mail/SKILL.md +3 -3
- package/skills/send-response/SKILL.md +6 -6
- package/skills/store-file/SKILL.md +4 -4
- package/skills/test-http/SKILL.md +5 -5
- package/skills/test-service/SKILL.md +5 -5
- package/skills/update-packages/SKILL.md +6 -6
- package/skills/upload-file/SKILL.md +7 -7
- package/skills/use-app-context/SKILL.md +7 -7
- package/skills/use-localization/SKILL.md +6 -6
- package/skills/use-middleware/SKILL.md +6 -6
- package/skills/use-model-transformers/SKILL.md +6 -6
- package/skills/use-repository/SKILL.md +7 -7
- package/skills/use-request-locals/SKILL.md +4 -4
- package/skills/validate-input/SKILL.md +7 -7
- package/skills/warlock-conventions/SKILL.md +6 -6
- package/skills/warlock-doctor/SKILL.md +5 -5
- package/skills/warlock-routes/SKILL.md +6 -6
- package/skills/wire-socket/SKILL.md +4 -4
- package/skills/write-cli-command/SKILL.md +6 -6
- package/skills/write-middleware/SKILL.md +8 -8
- package/skills/write-seeder/SKILL.md +5 -5
- package/skills/write-use-case/SKILL.md +3 -3
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 —
|
|
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 — the `use-app-context` topic; general config shape — the `configure-app` topic; competing pattern: hand-rolled process signal blocks, NestJS lifecycle hooks.'
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
# Warlock — add a connector
|
|
@@ -243,16 +243,16 @@ See the [Registering a connector](#registering-a-connector) section above for th
|
|
|
243
243
|
|
|
244
244
|
## See also
|
|
245
245
|
|
|
246
|
-
-
|
|
247
|
-
-
|
|
248
|
-
-
|
|
246
|
+
- The `configure-app` topic — `warlock.config.ts`, config files, env.
|
|
247
|
+
- The `use-app-context` topic — checking environment + paths inside `start()`.
|
|
248
|
+
- The `warlock-conventions` topic — module layout, canonical imports.
|
|
249
249
|
|
|
250
250
|
|
|
251
251
|
## benchmark-code `@warlock.js/core/benchmark-code/SKILL.md`
|
|
252
252
|
|
|
253
253
|
---
|
|
254
254
|
name: benchmark-code
|
|
255
|
-
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 —
|
|
255
|
+
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 — the `retry-operation` topic; benchmark config wiring — the `configure-app` topic; competing libs `prom-client`, `pino`, `perf_hooks`, `console.time`.'
|
|
256
256
|
---
|
|
257
257
|
|
|
258
258
|
# Warlock — benchmark code
|
|
@@ -504,15 +504,15 @@ The `latency` is the *total* time including retries — useful for the SLO you a
|
|
|
504
504
|
|
|
505
505
|
## See also
|
|
506
506
|
|
|
507
|
-
-
|
|
508
|
-
-
|
|
507
|
+
- The `retry-operation` topic — wrapping flaky operations with retry; composes inside `measure()`.
|
|
508
|
+
- The `configure-app` topic — wiring `src/config/benchmark.ts`.
|
|
509
509
|
|
|
510
510
|
|
|
511
511
|
## build-restful `@warlock.js/core/build-restful/SKILL.md`
|
|
512
512
|
|
|
513
513
|
---
|
|
514
514
|
name: build-restful
|
|
515
|
-
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 —
|
|
515
|
+
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 — the `register-route` topic; per-action controllers — the `create-controller` topic; wire mapping — the `define-resource` topic; competing pattern: hand-rolled controllers, `@nestjs/swagger` decorator-driven CRUD.'
|
|
516
516
|
---
|
|
517
517
|
|
|
518
518
|
# Warlock — build a RESTful resource
|
|
@@ -774,22 +774,22 @@ router.restfulResource("/orders", new OrdersRestful());
|
|
|
774
774
|
|
|
775
775
|
## See also
|
|
776
776
|
|
|
777
|
-
-
|
|
778
|
-
-
|
|
779
|
-
-
|
|
780
|
-
-
|
|
777
|
+
- The `register-route` topic — the wider router surface (`group`, `prefix`, plain verbs).
|
|
778
|
+
- The `create-controller` topic — what the chain's handlers look like.
|
|
779
|
+
- The `define-resource` topic — wire shape for the records the chain returns.
|
|
780
|
+
- The `warlock-conventions` topic — controller/service/repository layering rules.
|
|
781
781
|
|
|
782
782
|
|
|
783
783
|
## build-url `@warlock.js/core/build-url/SKILL.md`
|
|
784
784
|
|
|
785
785
|
---
|
|
786
786
|
name: build-url
|
|
787
|
-
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 —
|
|
787
|
+
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 — the `resolve-path` topic; signed CDN URLs — the `store-file` topic; resource output — the `define-resource` topic; competing patterns: hand-rolled `${baseUrl}/...` template strings.'
|
|
788
788
|
---
|
|
789
789
|
|
|
790
790
|
# Warlock — build a URL
|
|
791
791
|
|
|
792
|
-
Path helpers (
|
|
792
|
+
Path helpers (the `resolve-path` topic) give you absolute filesystem paths. URL helpers give you absolute HTTP URLs. Different jobs, often confused.
|
|
793
793
|
|
|
794
794
|
Use URL helpers whenever you need to render a string that goes into a browser, an HTTP client, or an email — `<img src=...>`, `<a href=...>`, an API response that includes a download link, a webhook payload.
|
|
795
795
|
|
|
@@ -957,18 +957,18 @@ Don't call `setBaseUrl` per request — it's process-global and races every othe
|
|
|
957
957
|
|
|
958
958
|
## See also
|
|
959
959
|
|
|
960
|
-
-
|
|
961
|
-
-
|
|
962
|
-
-
|
|
963
|
-
-
|
|
964
|
-
-
|
|
960
|
+
- The `resolve-path` topic — filesystem path helpers (`uploadsPath`, `publicPath`, ...). Use for read/write; use the URL helpers for rendering.
|
|
961
|
+
- The `store-file` topic — the `storage.url(path)` driver method, which can produce signed CDN URLs for non-local drivers (S3 etc.). Use that over `uploadsUrl` when you're on a remote driver.
|
|
962
|
+
- The `upload-file` topic — the `UploadedFile` lifecycle; where the path that feeds `uploadsUrl` comes from.
|
|
963
|
+
- The `define-resource` topic — the `url` / `uploadsUrl` / `storageUrl` casts (and resolver functions) are the right place to call URL helpers.
|
|
964
|
+
- The `configure-app` topic — `src/config/app.ts` and the `baseUrl` env wiring.
|
|
965
965
|
|
|
966
966
|
|
|
967
967
|
## configure-app `@warlock.js/core/configure-app/SKILL.md`
|
|
968
968
|
|
|
969
969
|
---
|
|
970
970
|
name: configure-app
|
|
971
|
-
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 —
|
|
971
|
+
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 — the `cache-basics` topic of the `warlock-js-cache` skill; mail config — the `send-mail` topic; storage config — the `store-file` topic; sitemap refusal on a missing origin — the `generate-sitemap` topic of the `warlock-js-web` skill; competing libs `dotenv` direct, `convict`, `node-config`.'
|
|
972
972
|
---
|
|
973
973
|
|
|
974
974
|
# Warlock — configure the app
|
|
@@ -1059,7 +1059,7 @@ for apps that don't opt in.
|
|
|
1059
1059
|
A malformed directive value (containing `;`, or with an unbalanced `'`
|
|
1060
1060
|
count) throws `InvalidCspDirectiveError` at boot, not silently — fix the
|
|
1061
1061
|
value in `src/config/http.ts` rather than expecting the framework to repair
|
|
1062
|
-
it. See
|
|
1062
|
+
it. See the `send-response` topic for how the
|
|
1063
1063
|
header lands on the response, and `@warlock.js/web`'s docs for how the
|
|
1064
1064
|
same nonce reaches the page's `<script>` tags.
|
|
1065
1065
|
|
|
@@ -1240,7 +1240,7 @@ requires the value. `@warlock.js/web`'s sitemap is the first such consumer:
|
|
|
1240
1240
|
with `web.sitemap.enabled: true` and no `app.publicUrl`/`PUBLIC_APP_URL` set,
|
|
1241
1241
|
generation refuses (`MissingPublicUrlError`, naming both) rather than falling
|
|
1242
1242
|
back to a request-derived host — a sitemap pointing at the wrong host is
|
|
1243
|
-
worse than none. See
|
|
1243
|
+
worse than none. See the `generate-sitemap` topic of the `warlock-js-web` skill.
|
|
1244
1244
|
|
|
1245
1245
|
## Common patterns
|
|
1246
1246
|
|
|
@@ -1270,17 +1270,17 @@ Internal `@warlock.js/*` packages read from `config.get("<name>")` the same way
|
|
|
1270
1270
|
|
|
1271
1271
|
## See also
|
|
1272
1272
|
|
|
1273
|
-
-
|
|
1274
|
-
-
|
|
1275
|
-
-
|
|
1276
|
-
-
|
|
1273
|
+
- The `warlock-conventions` topic — module layout, canonical imports, framework-wide invariants.
|
|
1274
|
+
- The `pick-cache-driver` topic of the `warlock-js-cache` skill — picking and registering a cache driver in `src/config/cache.ts`.
|
|
1275
|
+
- The `send-mail` topic — the `src/config/mail.ts` shape.
|
|
1276
|
+
- The `store-file` topic — the `src/config/storage.ts` shape.
|
|
1277
1277
|
|
|
1278
1278
|
|
|
1279
1279
|
## create-controller `@warlock.js/core/create-controller/SKILL.md`
|
|
1280
1280
|
|
|
1281
1281
|
---
|
|
1282
1282
|
name: create-controller
|
|
1283
|
-
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`, `controller.responseSchema`, `response.success`, `response.successCreate`; "write a controller", "attach a schema to a handler", "thin controller pattern", "guarded request type", "type the API response"; typical import `import { type RequestHandler } from "@warlock.js/core"`. Skip: response helper menu —
|
|
1283
|
+
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`, `controller.responseSchema`, `response.success`, `response.successCreate`; "write a controller", "attach a schema to a handler", "thin controller pattern", "guarded request type", "type the API response"; typical import `import { type RequestHandler } from "@warlock.js/core"`. Skip: response helper menu — the `send-response` topic; schema authoring — the `validate-input` topic; URL wiring — the `register-route` topic; competing patterns: `express` middleware functions, `@nestjs/common` `@Controller`/`@Get` decorators.'
|
|
1284
1284
|
---
|
|
1285
1285
|
|
|
1286
1286
|
# Warlock — create a controller
|
|
@@ -1328,7 +1328,7 @@ Prefer `request.validated()` once a schema is attached — it's typed.
|
|
|
1328
1328
|
| Content type | Parsed by | Notes |
|
|
1329
1329
|
| ------------------------------------ | -------------------------------- | --------------------------------------------------------------------- |
|
|
1330
1330
|
| `application/json` | Fastify (built-in) | objects/arrays parsed as-is |
|
|
1331
|
-
| `multipart/form-data` | `@fastify/multipart` | fields + files; see
|
|
1331
|
+
| `multipart/form-data` | `@fastify/multipart` | fields + files; see the `upload-file` topic |
|
|
1332
1332
|
| `application/x-www-form-urlencoded` | Warlock's own content-type parser (`http/parse-urlencoded-body.ts`) | plain HTML forms, OAuth `form_post` callbacks (e.g. Apple Sign in) |
|
|
1333
1333
|
|
|
1334
1334
|
For urlencoded bodies: fields decode via `URLSearchParams`. A key sent more than once (`tag=a&tag=b`) becomes an array (`request.input("tag")` → `["a", "b"]`); every other key is a plain string. Bracket-notation keys (`a[b]=1`) are **not** expanded by the urlencoded parser itself — nesting only happens through the same shared bracket-key logic every body type already goes through, so it behaves exactly like a JSON or query-string key of that shape, no differently than today.
|
|
@@ -1337,7 +1337,7 @@ All three content types are held to the same `http.bodyLimit` — an over-limit
|
|
|
1337
1337
|
|
|
1338
1338
|
## Returning output
|
|
1339
1339
|
|
|
1340
|
-
Pick the helper that matches the outcome. Full surface in
|
|
1340
|
+
Pick the helper that matches the outcome. Full surface in the `send-response` topic. Quick map:
|
|
1341
1341
|
|
|
1342
1342
|
| Helper | Status | Use when |
|
|
1343
1343
|
| ---------------------------------- | ------ | ----------------------------- |
|
|
@@ -1414,7 +1414,7 @@ Use `RequestHandler<Request<TSchema>>` for public routes, `GuardedRequestHandler
|
|
|
1414
1414
|
createProductController.description = "Create a new product (admin only)";
|
|
1415
1415
|
```
|
|
1416
1416
|
|
|
1417
|
-
`description` feeds the OpenAPI document (`warlock generate.openapi`, see
|
|
1417
|
+
`description` feeds the OpenAPI document (`warlock generate.openapi`, see the `generate-openapi` topic) and surfaces in dev-server logs.
|
|
1418
1418
|
|
|
1419
1419
|
## Declaring response types with `responseSchema`
|
|
1420
1420
|
|
|
@@ -1542,7 +1542,7 @@ export const getProductController: RequestHandler = async ({ request, response }
|
|
|
1542
1542
|
};
|
|
1543
1543
|
```
|
|
1544
1544
|
|
|
1545
|
-
No `if (!product)` branch in the controller. The error class carries the HTTP semantic (`404` for `ResourceNotFoundError`, `403` for `ForbiddenError`, `400` for `BadRequestError`, `409` for `ConflictError`, `500` for `ServerError`). Full list in
|
|
1545
|
+
No `if (!product)` branch in the controller. The error class carries the HTTP semantic (`404` for `ResourceNotFoundError`, `403` for `ForbiddenError`, `400` for `BadRequestError`, `409` for `ConflictError`, `500` for `ServerError`). Full list in the `send-response` topic ("Throwing HTTP errors" section). `product.notFound` is a translation key — see localization conventions in your project's `utils/locales.ts`.
|
|
1546
1546
|
|
|
1547
1547
|
## Gotchas
|
|
1548
1548
|
|
|
@@ -1553,16 +1553,16 @@ No `if (!product)` branch in the controller. The error class carries the HTTP se
|
|
|
1553
1553
|
|
|
1554
1554
|
## See also
|
|
1555
1555
|
|
|
1556
|
-
-
|
|
1557
|
-
-
|
|
1558
|
-
-
|
|
1556
|
+
- The `register-route` topic — wiring a controller to a URL.
|
|
1557
|
+
- The `send-response` topic — full Response helper surface.
|
|
1558
|
+
- The `warlock-conventions` topic — controller-service-repository layering.
|
|
1559
1559
|
|
|
1560
1560
|
|
|
1561
1561
|
## create-module `@warlock.js/core/create-module/SKILL.md`
|
|
1562
1562
|
|
|
1563
1563
|
---
|
|
1564
1564
|
name: create-module
|
|
1565
|
-
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 —
|
|
1565
|
+
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 — the `warlock-conventions` topic; routes file shape — the `register-route` topic; controller shape — the `create-controller` topic; competing tooling: `@nestjs/cli`, `hygen`, hand-rolled folder layouts.'
|
|
1566
1566
|
---
|
|
1567
1567
|
|
|
1568
1568
|
# Warlock — create a module
|
|
@@ -1742,21 +1742,21 @@ await warmupProductCache();
|
|
|
1742
1742
|
|
|
1743
1743
|
## See also
|
|
1744
1744
|
|
|
1745
|
-
-
|
|
1746
|
-
-
|
|
1747
|
-
-
|
|
1748
|
-
-
|
|
1749
|
-
-
|
|
1750
|
-
-
|
|
1751
|
-
-
|
|
1752
|
-
-
|
|
1745
|
+
- The `warlock-conventions` topic — module layout, file suffixes, path aliases.
|
|
1746
|
+
- The `register-route` topic — what to put in `routes.ts`.
|
|
1747
|
+
- The `create-controller` topic — the handler shape, attaching validation.
|
|
1748
|
+
- The `use-repository` topic — what the generated `<module>.repository.ts` looks like and how to extend it.
|
|
1749
|
+
- The `define-resource` topic — the output mapper for the model.
|
|
1750
|
+
- The `validate-input` topic — wiring `schema/*.schema.ts` to controllers.
|
|
1751
|
+
- The `write-seeder` topic — populating the generated `seeds/` folder.
|
|
1752
|
+
- The `use-localization` topic — populating the generated `utils/locales.ts`.
|
|
1753
1753
|
|
|
1754
1754
|
|
|
1755
1755
|
## define-resource `@warlock.js/core/define-resource/SKILL.md`
|
|
1756
1756
|
|
|
1757
1757
|
---
|
|
1758
1758
|
name: define-resource
|
|
1759
|
-
description: 'Map model fields to wire-shape via `defineResource()` or `Resource` subclasses. Output-only — never put business logic, hydration, or reconciliation in a resource. Also covers the typed output: `ResourceOutput<typeof R>`, `defineResource<Out>()`, `Serialized<T, W>` and `ModelResourceRegistry`. Triggers: `defineResource`, `Resource`, `RegisterResource`, `toJSON`, `ResourceOutput`, `Serialized`, `ModelResourceRegistry`, `"self"`, `"localized"`, `"uploadsUrl"`; "shape an API response", "type a resource''s output", "what does the client receive", "nest related resources", "rename a field on output", "self-referential tree resource"; typical import `import { defineResource } from "@warlock.js/core"`. Skip: localized columns —
|
|
1759
|
+
description: 'Map model fields to wire-shape via `defineResource()` or `Resource` subclasses. Output-only — never put business logic, hydration, or reconciliation in a resource. Also covers the typed output: `ResourceOutput<typeof R>`, `defineResource<Out>()`, `Serialized<T, W>` and `ModelResourceRegistry`. Triggers: `defineResource`, `Resource`, `RegisterResource`, `toJSON`, `ResourceOutput`, `Serialized`, `ModelResourceRegistry`, `"self"`, `"localized"`, `"uploadsUrl"`; "shape an API response", "type a resource''s output", "what does the client receive", "nest related resources", "rename a field on output", "self-referential tree resource"; typical import `import { defineResource } from "@warlock.js/core"`. Skip: localized columns — the `use-localization` topic; URL casting — the `build-url` topic; controller side — the `create-controller` topic; competing libs `@nestjs/swagger` `@ApiProperty`, `class-transformer`, hand-rolled DTO mappers.'
|
|
1760
1760
|
---
|
|
1761
1761
|
|
|
1762
1762
|
# Warlock — define a resource
|
|
@@ -2151,16 +2151,16 @@ export const CommentResource = defineResource({
|
|
|
2151
2151
|
|
|
2152
2152
|
## See also
|
|
2153
2153
|
|
|
2154
|
-
-
|
|
2155
|
-
-
|
|
2156
|
-
-
|
|
2154
|
+
- The `warlock-conventions` topic — the output-only rule and where logic actually lives.
|
|
2155
|
+
- The `build-restful` topic — wiring a resource into a CRUD pipeline.
|
|
2156
|
+
- The `create-controller` topic — calling `new XResource(record).toJSON()` from a controller.
|
|
2157
2157
|
|
|
2158
2158
|
|
|
2159
2159
|
## encrypt-data `@warlock.js/core/encrypt-data/SKILL.md`
|
|
2160
2160
|
|
|
2161
2161
|
---
|
|
2162
2162
|
name: encrypt-data
|
|
2163
|
-
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 —
|
|
2163
|
+
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 — the `hash-password` topic; config wiring — the `configure-app` topic; competing libs Node `crypto` direct, `crypto-js`, `libsodium-wrappers`.'
|
|
2164
2164
|
---
|
|
2165
2165
|
|
|
2166
2166
|
# Warlock — encrypt and fingerprint
|
|
@@ -2172,7 +2172,7 @@ Two helpers, two different jobs:
|
|
|
2172
2172
|
| `encrypt` / `decrypt` | reversible | AES-256-GCM | Secrets you need to read back (API keys, OAuth tokens). |
|
|
2173
2173
|
| `hmacHash` | one-way | HMAC-SHA256 | Deterministic fingerprint for lookup/dedup of encrypted values. |
|
|
2174
2174
|
|
|
2175
|
-
Both live in `@warlock.js/core`. For **password hashing** (a one-way job with very different requirements), reach for
|
|
2175
|
+
Both live in `@warlock.js/core`. For **password hashing** (a one-way job with very different requirements), reach for the `hash-password` topic instead — bcrypt is the right tool there, not encrypt.
|
|
2176
2176
|
|
|
2177
2177
|
## The shape
|
|
2178
2178
|
|
|
@@ -2284,7 +2284,7 @@ await idempotencyKeysRepository.first({ hash: hmacHash(JSON.stringify(request))
|
|
|
2284
2284
|
log.info("api-key", "used", { fingerprint: hmacHash(apiKey).slice(0, 8) });
|
|
2285
2285
|
```
|
|
2286
2286
|
|
|
2287
|
-
**Do not use `hmacHash` for passwords.** It's fast — a brute-force attack with a stolen database would clear common passwords in minutes. That's what bcrypt is for (see
|
|
2287
|
+
**Do not use `hmacHash` for passwords.** It's fast — a brute-force attack with a stolen database would clear common passwords in minutes. That's what bcrypt is for (see the `hash-password` topic).
|
|
2288
2288
|
|
|
2289
2289
|
## Common patterns
|
|
2290
2290
|
|
|
@@ -2359,20 +2359,20 @@ Same payload → same key → returns the cached result. Different keys (because
|
|
|
2359
2359
|
|
|
2360
2360
|
`encrypt` / `decrypt` / `hmacHash` use Node's built-in `crypto` — no extra dependency. They're available out of the box.
|
|
2361
2361
|
|
|
2362
|
-
Password hashing (`hashPassword`) needs `bcryptjs`, which is its own install — see
|
|
2362
|
+
Password hashing (`hashPassword`) needs `bcryptjs`, which is its own install — see the `hash-password` topic.
|
|
2363
2363
|
|
|
2364
2364
|
## See also
|
|
2365
2365
|
|
|
2366
|
-
-
|
|
2367
|
-
-
|
|
2368
|
-
-
|
|
2366
|
+
- The `hash-password` topic — bcrypt password hashing (the third member of the encryption module, but a different job entirely).
|
|
2367
|
+
- The `configure-app` topic — `src/config/encryption.ts` and env wiring.
|
|
2368
|
+
- The `warlock-conventions` topic — service layering, where the encryption boundary should sit.
|
|
2369
2369
|
|
|
2370
2370
|
|
|
2371
2371
|
## generate-openapi `@warlock.js/core/generate-openapi/SKILL.md`
|
|
2372
2372
|
|
|
2373
2373
|
---
|
|
2374
2374
|
name: generate-openapi
|
|
2375
|
-
description: 'Generate an OpenAPI 3.1 document from the registered routes with `warlock generate.openapi` (default `storage/openapi/openapi.json`), write a Postman collection from it with `warlock generate.postman` (default `storage/postman/collection.json`), and read it live in the dev-only API docs page at `/__warlock/docs`. Documents paths, path/query parameters, request bodies from Seal validation, responses from `handler.responseSchema`, 401/422 and bearer/cookie security from `authMiddleware()`. Triggers: `generate.openapi`, `openApiGeneratorCommand`, `buildOpenApiDocument`, `getDevelopmentOpenApiDocument`, `generate.postman`, `openApiToPostmanCollection`, `getDevelopmentPostmanCollection`, `responseSchema`, `--include-pages`, `/__warlock/docs`; "OpenAPI", "Swagger", "API docs", "import my API into Postman or Insomnia", "document my routes". Skip: declaring response types on a handler —
|
|
2375
|
+
description: 'Generate an OpenAPI 3.1 document from the registered routes with `warlock generate.openapi` (default `storage/openapi/openapi.json`), write a Postman collection from it with `warlock generate.postman` (default `storage/postman/collection.json`), and read it live in the dev-only API docs page at `/__warlock/docs`. Documents paths, path/query parameters, request bodies from Seal validation, responses from `handler.responseSchema`, 401/422 and bearer/cookie security from `authMiddleware()`. Triggers: `generate.openapi`, `openApiGeneratorCommand`, `buildOpenApiDocument`, `getDevelopmentOpenApiDocument`, `generate.postman`, `openApiToPostmanCollection`, `getDevelopmentPostmanCollection`, `responseSchema`, `--include-pages`, `/__warlock/docs`; "OpenAPI", "Swagger", "API docs", "import my API into Postman or Insomnia", "document my routes". Skip: declaring response types on a handler — the `create-controller` topic; the devtools dashboard — the `devtools-overview` topic of the `warlock-js-devtools` skill; listing routes — the `warlock-routes` topic.'
|
|
2376
2376
|
---
|
|
2377
2377
|
|
|
2378
2378
|
# Warlock — generate an OpenAPI document
|
|
@@ -2416,7 +2416,7 @@ npx warlock generate.openapi --out docs/openapi.json --title "Shop API" --server
|
|
|
2416
2416
|
|
|
2417
2417
|
### Responses from `responseSchema`
|
|
2418
2418
|
|
|
2419
|
-
The grammar is the one described in
|
|
2419
|
+
The grammar is the one described in the `create-controller` topic ("Declaring response types with `responseSchema`" section): cast strings with suffixes, a resource, `[Resource]`, nested objects.
|
|
2420
2420
|
|
|
2421
2421
|
```ts
|
|
2422
2422
|
loginController.responseSchema = {
|
|
@@ -2515,23 +2515,23 @@ const { document, warnings } = buildOpenApiDocument(router.list(), {
|
|
|
2515
2515
|
|
|
2516
2516
|
## See also
|
|
2517
2517
|
|
|
2518
|
-
-
|
|
2519
|
-
-
|
|
2520
|
-
-
|
|
2518
|
+
- The `create-controller` topic — `validation`, `description` and `responseSchema` on a handler.
|
|
2519
|
+
- The `define-resource` topic — resources, which become `components.schemas`.
|
|
2520
|
+
- The `warlock-routes` topic — list the routes the document is built from.
|
|
2521
2521
|
|
|
2522
2522
|
|
|
2523
2523
|
## hash-password `@warlock.js/core/hash-password/SKILL.md`
|
|
2524
2524
|
|
|
2525
2525
|
---
|
|
2526
2526
|
name: hash-password
|
|
2527
|
-
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 —
|
|
2527
|
+
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 — the `encrypt-data` topic; the other transformers — the `use-model-transformers` topic; config wiring — the `configure-app` topic; competing libs `bcrypt` native, `argon2`, `scrypt`.'
|
|
2528
2528
|
---
|
|
2529
2529
|
|
|
2530
2530
|
# Warlock — hash a password
|
|
2531
2531
|
|
|
2532
2532
|
For storing user-typed passwords, bcrypt is the one right answer — and the only one. It's **deliberately slow** (~250ms per call with the default salt rounds), which is what makes it expensive to brute-force a stolen password database. Use it for nothing else: not API keys, not session tokens, not "this needs to be one-way."
|
|
2533
2533
|
|
|
2534
|
-
If your value needs to be read back later →
|
|
2534
|
+
If your value needs to be read back later → the `encrypt-data` topic.
|
|
2535
2535
|
If you need a fast searchable fingerprint of an encrypted value → also `encrypt-data` (`hmacHash`).
|
|
2536
2536
|
|
|
2537
2537
|
## The shape
|
|
@@ -2692,7 +2692,7 @@ There is no `warlock add` feature for password hashing — `bcryptjs` is a plain
|
|
|
2692
2692
|
|
|
2693
2693
|
## Gotchas
|
|
2694
2694
|
|
|
2695
|
-
- **Never use `hashPassword` for non-password values.** A 250ms tax on every API request because someone reached for it as a "general one-way hash" — that's a performance bug waiting to happen. For one-way fingerprinting of encrypted values, use `hmacHash` (see
|
|
2695
|
+
- **Never use `hashPassword` for non-password values.** A 250ms tax on every API request because someone reached for it as a "general one-way hash" — that's a performance bug waiting to happen. For one-way fingerprinting of encrypted values, use `hmacHash` (see the `encrypt-data` topic).
|
|
2696
2696
|
- **Don't `hashPassword` on the request hot path twice.** Each call is ~250ms. If you `hashPassword(input)` then call it again as part of `verifyPassword`'s internals (you don't), you're stacking the tax. `verifyPassword(plain, storedHash)` takes the plaintext and the stored hash — that's the API.
|
|
2697
2697
|
- **Don't swap `bcryptjs` for native `bcrypt` without a reason.** `bcryptjs` is portable across every platform (no native build), and the perf delta isn't meaningful in the password-verification workflow.
|
|
2698
2698
|
- **The transformer detects changes by comparison.** If your model's password field is `null` and you save `null` again, it's a no-op. If it's a hash and you save the same hash string, also no-op. Only an actual value change triggers re-hashing.
|
|
@@ -2700,18 +2700,18 @@ There is no `warlock add` feature for password hashing — `bcryptjs` is a plain
|
|
|
2700
2700
|
|
|
2701
2701
|
## See also
|
|
2702
2702
|
|
|
2703
|
-
-
|
|
2704
|
-
-
|
|
2705
|
-
-
|
|
2706
|
-
-
|
|
2707
|
-
-
|
|
2703
|
+
- The `use-model-transformers` topic — `useHashedPassword` + the two other model transformers (`useComputedSlug`, `useComputedModel`).
|
|
2704
|
+
- The `encrypt-data` topic — reversible AES-256-GCM `encrypt`/`decrypt` + one-way HMAC `hmacHash` (the other two members of the encryption module).
|
|
2705
|
+
- The `configure-app` topic — `src/config/encryption.ts` and the `password.salt` knob.
|
|
2706
|
+
- The `define-resource` topic — where to filter the password field out of API responses.
|
|
2707
|
+
- The `warlock-conventions` topic — service layering, where the password boundary should sit.
|
|
2708
2708
|
|
|
2709
2709
|
|
|
2710
2710
|
## health-checks `@warlock.js/core/health-checks/SKILL.md`
|
|
2711
2711
|
|
|
2712
2712
|
---
|
|
2713
2713
|
name: health-checks
|
|
2714
|
-
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 —
|
|
2714
|
+
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 — the `use-app-context` topic; maintenance-mode 503s — the `use-middleware` topic; connector lifecycle — the `add-connector` topic; competing libs `@fastify/under-pressure`, `terminus`, hand-rolled `/health` controllers.'
|
|
2715
2715
|
---
|
|
2716
2716
|
|
|
2717
2717
|
# Warlock — health checks & graceful shutdown
|
|
@@ -2820,21 +2820,21 @@ For an even smoother handoff, give the load balancer time to observe the 503 bef
|
|
|
2820
2820
|
- **`/health` is registered straight on Fastify, not the app router.** It's infra, so it's immune to HMR and route scanning — but if your app also defines a `/health` route you'll have a collision. Rename via `http.health.path`.
|
|
2821
2821
|
- **Readiness needs a finished boot.** Before `Application.isBooted` (e.g. while late-phase connectors are still starting) `/ready` is 503 by design — that's the point.
|
|
2822
2822
|
- **A hanging `onShutdown` hook delays the drain.** App hooks run before connector teardown and are only bounded by your process manager's kill timeout; keep them fast. The HTTP drain itself is bounded by `gracefulShutdown.timeout`.
|
|
2823
|
-
- **The `maintenance` middleware is a different 503.** It allowlists `/health` by default so probes pass during maintenance — but maintenance mode is operator-toggled downtime, not readiness. See
|
|
2823
|
+
- **The `maintenance` middleware is a different 503.** It allowlists `/health` by default so probes pass during maintenance — but maintenance mode is operator-toggled downtime, not readiness. See the `use-middleware` topic.
|
|
2824
2824
|
|
|
2825
2825
|
## See also
|
|
2826
2826
|
|
|
2827
|
-
-
|
|
2828
|
-
-
|
|
2829
|
-
-
|
|
2830
|
-
-
|
|
2827
|
+
- The `use-app-context` topic — `Application.onShutdown` / `onceBooted` / `isShuttingDown`, the lifecycle hooks the endpoints build on.
|
|
2828
|
+
- The `configure-app` topic — the `src/config/http.ts` shape.
|
|
2829
|
+
- The `add-connector` topic — connector boot/shutdown order, where draining slots in.
|
|
2830
|
+
- The `use-middleware` topic — maintenance mode and other built-in middleware.
|
|
2831
2831
|
|
|
2832
2832
|
|
|
2833
2833
|
## lower-stage3-decorators `@warlock.js/core/lower-stage3-decorators/SKILL.md`
|
|
2834
2834
|
|
|
2835
2835
|
---
|
|
2836
2836
|
name: lower-stage3-decorators
|
|
2837
|
-
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 —
|
|
2837
|
+
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 — the `test-service` topic / the `test-http` topic; runtime migrations — the `write-migration` topic of the `warlock-js-cascade` skill.'
|
|
2838
2838
|
---
|
|
2839
2839
|
|
|
2840
2840
|
# Lower Stage-3 decorators for Vite/Vitest
|
|
@@ -2885,16 +2885,16 @@ It's the **same esbuild transform the production `tsx`/build path uses**, so a f
|
|
|
2885
2885
|
|
|
2886
2886
|
## See also
|
|
2887
2887
|
|
|
2888
|
-
-
|
|
2889
|
-
-
|
|
2890
|
-
-
|
|
2888
|
+
- The `test-service` topic — `setupTest()` bootstrap for unit-testing services/models once the harness loads.
|
|
2889
|
+
- The `test-http` topic — integration tests over the real HTTP server.
|
|
2890
|
+
- The `write-migration` topic of the `warlock-js-cascade` skill — the decorated models this plugin lets you load.
|
|
2891
2891
|
|
|
2892
2892
|
|
|
2893
2893
|
## process-image `@warlock.js/core/process-image/SKILL.md`
|
|
2894
2894
|
|
|
2895
2895
|
---
|
|
2896
2896
|
name: process-image
|
|
2897
|
-
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 —
|
|
2897
|
+
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 — the `upload-file` topic; storage persistence — the `store-file` topic; competing libs `sharp` direct, `jimp`, `imagemagick`, `gm`.'
|
|
2898
2898
|
---
|
|
2899
2899
|
|
|
2900
2900
|
# Warlock — process an image
|
|
@@ -3047,7 +3047,7 @@ The wrapper exposes the underlying `sharp.Sharp` via `.image` for anything not s
|
|
|
3047
3047
|
|
|
3048
3048
|
`UploadedFile` (from multipart uploads) has its own chainable `.resize().format().quality().save(...)` that runs through `Image` internally — same deferred execution, same transforms. Use it when the source is a multipart upload; reach for `new Image(...)` directly when the source is a buffer/path/URL.
|
|
3049
3049
|
|
|
3050
|
-
See
|
|
3050
|
+
See the `upload-file` topic for the multipart entry point and the `store-file` topic for persisting the output through storage drivers.
|
|
3051
3051
|
|
|
3052
3052
|
## Gotchas
|
|
3053
3053
|
|
|
@@ -3060,16 +3060,16 @@ See [`upload-file`](../upload-file/SKILL.md) for the multipart entry point and [
|
|
|
3060
3060
|
|
|
3061
3061
|
## See also
|
|
3062
3062
|
|
|
3063
|
-
-
|
|
3064
|
-
-
|
|
3065
|
-
-
|
|
3063
|
+
- The `upload-file` topic — multipart uploads, where image transforms typically start.
|
|
3064
|
+
- The `store-file` topic — persisting image output through storage drivers (local / S3 / R2 / Spaces).
|
|
3065
|
+
- The `warlock-conventions` topic — where image-processing services live.
|
|
3066
3066
|
|
|
3067
3067
|
|
|
3068
3068
|
## register-route `@warlock.js/core/register-route/SKILL.md`
|
|
3069
3069
|
|
|
3070
3070
|
---
|
|
3071
3071
|
name: register-route
|
|
3072
|
-
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 —
|
|
3072
|
+
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 — the `create-controller` topic; CRUD chain details — the `build-restful` topic; middleware authoring — the `write-middleware` topic; competing libs `express`, `fastify`, `koa`, `@nestjs/common`.'
|
|
3073
3073
|
---
|
|
3074
3074
|
|
|
3075
3075
|
# Warlock — register a route
|
|
@@ -3098,7 +3098,7 @@ router.post("/orders/:id", createOrderController, { name: "orders.create" });
|
|
|
3098
3098
|
Use a concrete HTTP verb for browser forms. `router.any()` is represented as
|
|
3099
3099
|
`all` metadata and requires callers to choose an explicit path and method.
|
|
3100
3100
|
|
|
3101
|
-
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
|
|
3101
|
+
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 the `create-controller` topic).
|
|
3102
3102
|
|
|
3103
3103
|
## HTTP verbs
|
|
3104
3104
|
|
|
@@ -3167,7 +3167,7 @@ router.prefix("/products", () => {
|
|
|
3167
3167
|
});
|
|
3168
3168
|
```
|
|
3169
3169
|
|
|
3170
|
-
If `guarded` doesn't exist in your project yet, see the shared utility convention in
|
|
3170
|
+
If `guarded` doesn't exist in your project yet, see the shared utility convention in the `warlock-conventions` topic.
|
|
3171
3171
|
|
|
3172
3172
|
## RESTful resource chain
|
|
3173
3173
|
|
|
@@ -3236,16 +3236,16 @@ router.get(["/health", "/healthz"], healthController);
|
|
|
3236
3236
|
|
|
3237
3237
|
## See also
|
|
3238
3238
|
|
|
3239
|
-
-
|
|
3240
|
-
-
|
|
3241
|
-
-
|
|
3239
|
+
- The `create-controller` topic — the handler shape, validation, request/response surface.
|
|
3240
|
+
- The `send-response` topic — picking the right `response.<helper>()`.
|
|
3241
|
+
- The `warlock-conventions` topic — module layout, the `guarded` convention, path aliases.
|
|
3242
3242
|
|
|
3243
3243
|
|
|
3244
3244
|
## request-memo `@warlock.js/core/request-memo/SKILL.md`
|
|
3245
3245
|
|
|
3246
3246
|
---
|
|
3247
3247
|
name: request-memo
|
|
3248
|
-
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 —
|
|
3248
|
+
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 — the `use-request-locals` topic; process-wide or cross-request caching — the `use-middleware` topic; competing patterns: dynamic `request[key]` properties, module-global `Map`, payload `request.get()` / `request.set()`.'
|
|
3249
3249
|
---
|
|
3250
3250
|
|
|
3251
3251
|
# Warlock — memoize work for one request
|
|
@@ -3382,16 +3382,16 @@ Reusing one key for different result types is a caller bug: TypeScript cannot co
|
|
|
3382
3382
|
|
|
3383
3383
|
## See also
|
|
3384
3384
|
|
|
3385
|
-
-
|
|
3386
|
-
-
|
|
3387
|
-
-
|
|
3385
|
+
- The `use-request-locals` topic — typed per-request data written by middleware.
|
|
3386
|
+
- The `write-middleware` topic — authoring and registering middleware.
|
|
3387
|
+
- The `create-controller` topic — consuming request-scoped values from controllers.
|
|
3388
3388
|
|
|
3389
3389
|
|
|
3390
3390
|
## request-tracing `@warlock.js/core/request-tracing/SKILL.md`
|
|
3391
3391
|
|
|
3392
3392
|
---
|
|
3393
3393
|
name: request-tracing
|
|
3394
|
-
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`) —
|
|
3394
|
+
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`) — the `use-middleware` topic; app-level structured logging — the `logger-basics` topic of the `warlock-js-logger` skill; competing libs `@opentelemetry/api` direct instrumentation, `express-request-id`, hand-rolled `X-Trace-Id` middleware.'
|
|
3395
3395
|
---
|
|
3396
3396
|
|
|
3397
3397
|
# Warlock — request tracing hooks
|
|
@@ -3522,7 +3522,7 @@ instead of adding a separate hook API. They add three phases:
|
|
|
3522
3522
|
trace keeps the same id through Warlock.
|
|
3523
3523
|
2. Otherwise `traceId` falls back to `request.id` (the framework's own
|
|
3524
3524
|
per-request correlation id — see
|
|
3525
|
-
|
|
3525
|
+
the `use-middleware` topic (its "Request ID correlation" section)
|
|
3526
3526
|
for how that id is generated/inherited/echoed).
|
|
3527
3527
|
|
|
3528
3528
|
`ctx.requestId` is always `request.id`, regardless of which branch produced
|
|
@@ -3543,7 +3543,7 @@ deriveTraceId(undefined, "req-abc123");
|
|
|
3543
3543
|
|
|
3544
3544
|
Tracing does **not** add a response header of its own. `core` already echoes
|
|
3545
3545
|
`request.id` back as `X-Request-Id` on every response (see
|
|
3546
|
-
|
|
3546
|
+
the `use-middleware` topic, "Request ID correlation" section) —
|
|
3547
3547
|
apps correlate through that existing header. When a valid inbound
|
|
3548
3548
|
`traceparent` is present, `ctx.traceId` inside your hooks carries that trace
|
|
3549
3549
|
id even though the response header still reflects `request.id`; if you need
|
|
@@ -3617,16 +3617,16 @@ export default {
|
|
|
3617
3617
|
|
|
3618
3618
|
## See also
|
|
3619
3619
|
|
|
3620
|
-
-
|
|
3621
|
-
-
|
|
3622
|
-
-
|
|
3620
|
+
- The `use-middleware` topic ("Request ID correlation" section) — `X-Request-Id` inheritance/echo, the header tracing correlates through.
|
|
3621
|
+
- The `use-app-context` topic — request-scoped ALS context (`request`/`response`) tracing hooks run inside.
|
|
3622
|
+
- The `logger-basics` topic of the `warlock-js-logger` skill — structured logging; tracing hooks are the place to bridge phase timing into your log channel.
|
|
3623
3623
|
|
|
3624
3624
|
|
|
3625
3625
|
## resolve-path `@warlock.js/core/resolve-path/SKILL.md`
|
|
3626
3626
|
|
|
3627
3627
|
---
|
|
3628
3628
|
name: resolve-path
|
|
3629
|
-
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 —
|
|
3629
|
+
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 — the `build-url` topic; app metadata — the `use-app-context` topic; storage abstraction — the `store-file` topic; competing patterns: `path.join(process.cwd(), ...)`, hand-rolled directory constants.'
|
|
3630
3630
|
---
|
|
3631
3631
|
|
|
3632
3632
|
# Warlock — resolve a path
|
|
@@ -3789,18 +3789,18 @@ If you find yourself reaching for `path.join(process.cwd(), ...)` — that's a s
|
|
|
3789
3789
|
|
|
3790
3790
|
## See also
|
|
3791
3791
|
|
|
3792
|
-
-
|
|
3793
|
-
-
|
|
3794
|
-
-
|
|
3795
|
-
-
|
|
3796
|
-
-
|
|
3792
|
+
- The `build-url` topic — HTTP URL helpers (`url`, `uploadsUrl`, `publicUrl`, `assetsUrl`) — companion for rendering URLs (not filesystem paths).
|
|
3793
|
+
- The `use-app-context` topic — `Application` static (env, runtime strategy, version, uptime) + `app` runtime accessor (Fastify, socket.io, router, database).
|
|
3794
|
+
- The `configure-app` topic — `src/config/uploads.ts` for the `root` override.
|
|
3795
|
+
- The `store-file` topic — the storage abstraction (most uploads code goes through `storage.put(...)`, not raw paths).
|
|
3796
|
+
- The `upload-file` topic — the `UploadedFile` shape that pairs with `uploadsPath`.
|
|
3797
3797
|
|
|
3798
3798
|
|
|
3799
3799
|
## retry-operation `@warlock.js/core/retry-operation/SKILL.md`
|
|
3800
3800
|
|
|
3801
3801
|
---
|
|
3802
3802
|
name: retry-operation
|
|
3803
|
-
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 —
|
|
3803
|
+
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 — the `benchmark-code` topic; use-case-level `retry` option — the `write-use-case` topic; competing libs `p-retry`, `async-retry`, `cockatiel`.'
|
|
3804
3804
|
---
|
|
3805
3805
|
|
|
3806
3806
|
# Warlock — retry an operation
|
|
@@ -3893,7 +3893,7 @@ const result = await measure("publish-event", () =>
|
|
|
3893
3893
|
|
|
3894
3894
|
## Use-case integration
|
|
3895
3895
|
|
|
3896
|
-
`useCase()` accepts a `retry` option (the same `RetryOptions`) that wraps the **handler** — see
|
|
3896
|
+
`useCase()` accepts a `retry` option (the same `RetryOptions`) that wraps the **handler** — see the `write-use-case` topic. Reach for that when "retry" means "re-run the handler"; reach for raw `retry()` when only one step inside is flaky.
|
|
3897
3897
|
|
|
3898
3898
|
## Gotchas
|
|
3899
3899
|
|
|
@@ -3905,15 +3905,15 @@ const result = await measure("publish-event", () =>
|
|
|
3905
3905
|
## See also
|
|
3906
3906
|
|
|
3907
3907
|
- [`mongez-reinforcements-async`](mongez-reinforcements-async) — full `retry` / `retryable` reference.
|
|
3908
|
-
-
|
|
3909
|
-
-
|
|
3908
|
+
- The `benchmark-code` topic — timing retried operations.
|
|
3909
|
+
- The `write-use-case` topic — the use-case `retry` option.
|
|
3910
3910
|
|
|
3911
3911
|
|
|
3912
3912
|
## run-app `@warlock.js/core/run-app/SKILL.md`
|
|
3913
3913
|
|
|
3914
3914
|
---
|
|
3915
3915
|
name: run-app
|
|
3916
|
-
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 —
|
|
3916
|
+
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 — the `write-cli-command` topic; config shape — the `configure-app` topic; competing tooling `nodemon`, `tsx`, `ts-node-dev`, `esbuild` direct.'
|
|
3917
3917
|
---
|
|
3918
3918
|
|
|
3919
3919
|
# Warlock — run the app
|
|
@@ -3959,7 +3959,7 @@ Once the server is ready, `warlock dev` listens for single keypresses:
|
|
|
3959
3959
|
| `c` | Clear the console. |
|
|
3960
3960
|
| `q` | Graceful shutdown, exit `0` — the same path as `Ctrl+C`. |
|
|
3961
3961
|
| `h` | Print the shortcuts that are armed right now. |
|
|
3962
|
-
| `u` | **Only while an update notice is showing** — update every `@warlock.js/*` package, install, and restart. See
|
|
3962
|
+
| `u` | **Only while an update notice is showing** — update every `@warlock.js/*` package, install, and restart. See the `update-packages` topic. |
|
|
3963
3963
|
| `Ctrl+C` | Graceful shutdown, unchanged. |
|
|
3964
3964
|
|
|
3965
3965
|
A "restart" is a fresh process (`r` and `u` both use it) — see [The supervisor](#the-supervisor) below for how that works.
|
|
@@ -4065,7 +4065,7 @@ export default defineConfig({
|
|
|
4065
4065
|
- **`generateTypings`** — turn off if you're committing generated typings and don't want them rewritten on every boot. The `--skip-typings` flag is the per-run version.
|
|
4066
4066
|
- **`healthCheckers`** — custom file health checker contracts (or `false` to disable). The `--skip-health` flag is the per-run version.
|
|
4067
4067
|
- **`transpileCacheDebug`** — diagnostic only. Names `.warlock/transpile/*.js` files `<slug>.<hash>.js` and appends `// @source <path>` markers so you can eyeball which cache entry came from which source. Leave off in normal use.
|
|
4068
|
-
- **`checkForUpdates`** — on `warlock dev` start, check npm for a newer `@warlock.js/core` and print a one-line notice if one exists. Best-effort and non-blocking; auto-skipped in CI and non-TTY shells. In an interactive terminal the notice arms a **`u` shortcut** that updates every `@warlock.js/*` package, installs, and restarts the server; elsewhere it prints `npx warlock update` instead. The registry answer is cached for 24h in `.warlock/update-check.json`, so a day of restarts costs one lookup. See
|
|
4068
|
+
- **`checkForUpdates`** — on `warlock dev` start, check npm for a newer `@warlock.js/core` and print a one-line notice if one exists. Best-effort and non-blocking; auto-skipped in CI and non-TTY shells. In an interactive terminal the notice arms a **`u` shortcut** that updates every `@warlock.js/*` package, installs, and restarts the server; elsewhere it prints `npx warlock update` instead. The registry answer is cached for 24h in `.warlock/update-check.json`, so a day of restarts costs one lookup. See the `update-packages` topic.
|
|
4069
4069
|
- **`restartOnConfigChange`** — restart the dev server when `warlock.config.ts` or any `.env*` changes (default `true`). Set `false` to get a warning instead and restart by hand. Neither file can be hot-reloaded, so without a restart the running services keep the old values.
|
|
4070
4070
|
- **`timings`** — print a one-line, per-phase breakdown next to the `hmr update` line on every hot reload: `watcher`, `debounce`, `graph`, `reimport`, `connectors`. `watcher` is the raw-fs-notification-to-stabilised-event gap (chokidar's `awaitWriteFinish` window); `debounce` is the handler's own adaptive wait; the rest are self-explanatory. Opt-in, off by default — a disabled flag costs one boolean check per reload, since the watcher-settle bookkeeping only runs when this is on. Use it to see which phase a slow reload is actually spending time in.
|
|
4071
4071
|
|
|
@@ -4132,7 +4132,7 @@ It exists so `warlock start` can tell a promoted build from a directory that mer
|
|
|
4132
4132
|
|
|
4133
4133
|
`warlock start` uses the same `resolveBuildConfig()` helper to find the bundle, so the two commands stay in sync no matter how you override the config. If `build` and `start` disagree on where the bundle is, it's because `warlock.config.ts` is being read with different cwds — never the case in normal operation.
|
|
4134
4134
|
|
|
4135
|
-
If the app uses `@warlock.js/web` page routes, a successful `warlock build` also writes `page-routes.manifest.json` next to the bundle (same `outdir`) — the snapshot `warlock routes:diff` compares the live dev surface against. See
|
|
4135
|
+
If the app uses `@warlock.js/web` page routes, a successful `warlock build` also writes `page-routes.manifest.json` next to the bundle (same `outdir`) — the snapshot `warlock routes:diff` compares the live dev surface against. See the `warlock-routes` topic (its `routes:diff` section).
|
|
4136
4136
|
|
|
4137
4137
|
## `warlock start` — run the production bundle
|
|
4138
4138
|
|
|
@@ -4309,7 +4309,7 @@ If you need the same fact inside the app, use `Application.onceBooted()` / `Appl
|
|
|
4309
4309
|
|
|
4310
4310
|
`*` — `environment` follows `NODE_ENV`. The dev command doesn't force it, but the default in most projects is `development`. `start` doesn't force it either; deployments set `NODE_ENV=production` themselves.
|
|
4311
4311
|
|
|
4312
|
-
If you need conditional behavior, branch on `Application.environment` (the orthogonal "what world am I talking to?" axis), not `runtimeStrategy` (the "how is the framework itself running?" axis). See
|
|
4312
|
+
If you need conditional behavior, branch on `Application.environment` (the orthogonal "what world am I talking to?" axis), not `runtimeStrategy` (the "how is the framework itself running?" axis). See the `use-app-context` topic.
|
|
4313
4313
|
|
|
4314
4314
|
## Common patterns
|
|
4315
4315
|
|
|
@@ -4420,19 +4420,19 @@ NODE_OPTIONS=--max-old-space-size=4096 npx warlock start
|
|
|
4420
4420
|
|
|
4421
4421
|
## See also
|
|
4422
4422
|
|
|
4423
|
-
-
|
|
4424
|
-
-
|
|
4425
|
-
-
|
|
4426
|
-
-
|
|
4427
|
-
-
|
|
4428
|
-
-
|
|
4423
|
+
- The `write-cli-command` topic — author a custom CLI command + the rest of the built-in commands (migrate / seed / generate.* / add / storage.put / jwt.generate).
|
|
4424
|
+
- The `configure-app` topic — `warlock.config.ts` shape and `defineConfig`.
|
|
4425
|
+
- The `use-app-context` topic — `Application.environment` vs `Application.runtimeStrategy`.
|
|
4426
|
+
- The `add-connector` topic — Early vs Late connector phases (why HTTP/socket boot late in dev).
|
|
4427
|
+
- The `update-packages` topic — `warlock update` + the dev-server update notice (`devServer.checkForUpdates`).
|
|
4428
|
+
- The `warlock-routes` topic — `warlock routes` / `warlock routes:diff`, the latter comparing live page routes against the manifest `warlock build` writes.
|
|
4429
4429
|
|
|
4430
4430
|
|
|
4431
4431
|
## send-mail `@warlock.js/core/send-mail/SKILL.md`
|
|
4432
4432
|
|
|
4433
4433
|
---
|
|
4434
4434
|
name: send-mail
|
|
4435
|
-
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 —
|
|
4435
|
+
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 — the `configure-app` topic; layered service patterns — the `warlock-conventions` topic; competing libs `nodemailer` direct, `@sendgrid/mail`, `resend`, `mailgun.js`.'
|
|
4436
4436
|
---
|
|
4437
4437
|
|
|
4438
4438
|
# Warlock — send a mail
|
|
@@ -4830,15 +4830,15 @@ await Mail.to(user.email)
|
|
|
4830
4830
|
|
|
4831
4831
|
## See also
|
|
4832
4832
|
|
|
4833
|
-
-
|
|
4834
|
-
-
|
|
4833
|
+
- The `configure-app` topic — `src/config/mail.ts` shape and `env()` patterns.
|
|
4834
|
+
- The `warlock-conventions` topic — where mail-sending services live.
|
|
4835
4835
|
|
|
4836
4836
|
|
|
4837
4837
|
## send-response `@warlock.js/core/send-response/SKILL.md`
|
|
4838
4838
|
|
|
4839
4839
|
---
|
|
4840
4840
|
name: send-response
|
|
4841
|
-
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 —
|
|
4841
|
+
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 — the `create-controller` topic; route registration — the `register-route` topic; competing patterns: hand-rolled status codes via `reply.code(404).send(...)`, raw Fastify reply.'
|
|
4842
4842
|
---
|
|
4843
4843
|
|
|
4844
4844
|
# Warlock — send a response
|
|
@@ -4983,7 +4983,7 @@ export const getProductController: RequestHandler = async ({ request, response }
|
|
|
4983
4983
|
};
|
|
4984
4984
|
```
|
|
4985
4985
|
|
|
4986
|
-
See
|
|
4986
|
+
See the `create-controller` topic for the "throw from service, return from controller" pattern.
|
|
4987
4987
|
|
|
4988
4988
|
## Server-Sent Events
|
|
4989
4989
|
|
|
@@ -5063,7 +5063,7 @@ These mutate the response in place; chain or call before the final `return respo
|
|
|
5063
5063
|
### `Content-Security-Policy` (5.12.0)
|
|
5064
5064
|
|
|
5065
5065
|
Opt in via `http.csp.enabled` in `src/config/http.ts` (see
|
|
5066
|
-
|
|
5066
|
+
the `configure-app` topic for the full shape).
|
|
5067
5067
|
When enabled, every response through the shared request funnel
|
|
5068
5068
|
(`http/middleware/inject-request-context.ts`, the same seam that stamps
|
|
5069
5069
|
`X-Request-Id`) gets a `Content-Security-Policy` header — `-Report-Only`
|
|
@@ -5143,16 +5143,16 @@ return response.header("X-Cache", "HIT").replay({
|
|
|
5143
5143
|
|
|
5144
5144
|
## See also
|
|
5145
5145
|
|
|
5146
|
-
-
|
|
5147
|
-
-
|
|
5148
|
-
-
|
|
5146
|
+
- The `create-controller` topic — what calls `response.<helper>()` from.
|
|
5147
|
+
- The `register-route` topic — wiring the controller to a URL.
|
|
5148
|
+
- The `warlock-conventions` topic — when to use HTTP error helpers vs `throw`.
|
|
5149
5149
|
|
|
5150
5150
|
|
|
5151
5151
|
## store-file `@warlock.js/core/store-file/SKILL.md`
|
|
5152
5152
|
|
|
5153
5153
|
---
|
|
5154
5154
|
name: store-file
|
|
5155
|
-
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 —
|
|
5155
|
+
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 — the `upload-file` topic; image transforms — the `process-image` topic; storage config shape — the `configure-app` topic; competing libs `@aws-sdk/client-s3`, `multer`, `formidable`.'
|
|
5156
5156
|
---
|
|
5157
5157
|
|
|
5158
5158
|
# Warlock — store a file
|
|
@@ -5547,16 +5547,16 @@ Client `PUT`s the bytes straight to R2 — your server never sees them.
|
|
|
5547
5547
|
|
|
5548
5548
|
## See also
|
|
5549
5549
|
|
|
5550
|
-
-
|
|
5551
|
-
-
|
|
5552
|
-
-
|
|
5550
|
+
- The `configure-app` topic — `src/config/storage.ts` shape and `env()` patterns.
|
|
5551
|
+
- The `warlock-conventions` topic — module layout for upload flows (`src/app/uploads/`).
|
|
5552
|
+
- The `send-response` topic — `response.sendFile(absPath)` for serving local files.
|
|
5553
5553
|
|
|
5554
5554
|
|
|
5555
5555
|
## test-http `@warlock.js/core/test-http/SKILL.md`
|
|
5556
5556
|
|
|
5557
5557
|
---
|
|
5558
5558
|
name: test-http
|
|
5559
|
-
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 —
|
|
5559
|
+
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 — the `test-service` topic; controller shape — the `create-controller` topic; competing libs `supertest`, `light-my-request`, `nock`.'
|
|
5560
5560
|
---
|
|
5561
5561
|
|
|
5562
5562
|
# Warlock — HTTP integration tests
|
|
@@ -5906,17 +5906,17 @@ This is fine for normal test flow. It bites when you're inside a transaction the
|
|
|
5906
5906
|
|
|
5907
5907
|
## See also
|
|
5908
5908
|
|
|
5909
|
-
-
|
|
5910
|
-
-
|
|
5911
|
-
-
|
|
5912
|
-
-
|
|
5909
|
+
- The `test-service` topic — pure unit tests against services/repositories/models (no HTTP).
|
|
5910
|
+
- The `create-controller` topic — the controller shape your HTTP tests are exercising.
|
|
5911
|
+
- The `warlock-conventions` topic — module layout, where `tests/*.test.ts` files live.
|
|
5912
|
+
- The `write-cli-command` topic — `warlock add test` scaffolds both global + worker setup files.
|
|
5913
5913
|
|
|
5914
5914
|
|
|
5915
5915
|
## test-service `@warlock.js/core/test-service/SKILL.md`
|
|
5916
5916
|
|
|
5917
5917
|
---
|
|
5918
5918
|
name: test-service
|
|
5919
|
-
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 —
|
|
5919
|
+
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 — the `test-http` topic; warlock add test scaffold — the `write-cli-command` topic; competing tooling: jest direct, `supertest`, `nock`.'
|
|
5920
5920
|
---
|
|
5921
5921
|
|
|
5922
5922
|
# Warlock — test a service
|
|
@@ -6067,7 +6067,7 @@ export default defineConfig({
|
|
|
6067
6067
|
});
|
|
6068
6068
|
```
|
|
6069
6069
|
|
|
6070
|
-
The `mongezVite()` plugin handles TypeScript path resolution and the framework's module shape. Without it, your imports break the moment vitest tries to load a Warlock module. `lowerStage3Decorators()` goes **first** — it lets decorated Cascade models (`@RegisterModel`, …) load under Vitest 4 / Vite 8; see
|
|
6070
|
+
The `mongezVite()` plugin handles TypeScript path resolution and the framework's module shape. Without it, your imports break the moment vitest tries to load a Warlock module. `lowerStage3Decorators()` goes **first** — it lets decorated Cascade models (`@RegisterModel`, …) load under Vitest 4 / Vite 8; see the `lower-stage3-decorators` topic.
|
|
6071
6071
|
|
|
6072
6072
|
### Keep Vitest setup out of development
|
|
6073
6073
|
|
|
@@ -6307,9 +6307,9 @@ In both cases the guard's scope matches the resource's scope, which is the point
|
|
|
6307
6307
|
|
|
6308
6308
|
## See also
|
|
6309
6309
|
|
|
6310
|
-
-
|
|
6311
|
-
-
|
|
6312
|
-
-
|
|
6310
|
+
- The `test-http` topic — integration tests via the real HTTP server (`startHttpTestServer` + `testGet` / `testPost` / `expectJson`).
|
|
6311
|
+
- The `warlock-conventions` topic — where tests live in a module (`tests/*.test.ts`).
|
|
6312
|
+
- The `write-cli-command` topic — `warlock add test` for the initial scaffold.
|
|
6313
6313
|
|
|
6314
6314
|
## App modules and `importModule`
|
|
6315
6315
|
|
|
@@ -6326,7 +6326,7 @@ The generated `src/test-setup.ts` already does this. Without it, `setupTest()` u
|
|
|
6326
6326
|
|
|
6327
6327
|
---
|
|
6328
6328
|
name: update-packages
|
|
6329
|
-
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 —
|
|
6329
|
+
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 — the `run-app` topic; writing a custom command — the `write-cli-command` topic; installing a NEW feature package (auth, mail, storage) — that is `warlock add`; releasing/publishing the framework — workspace release tooling, not this command.'
|
|
6330
6330
|
---
|
|
6331
6331
|
|
|
6332
6332
|
# Warlock — update the framework
|
|
@@ -6405,7 +6405,7 @@ Pressing `u` on that notice runs the whole upgrade without leaving the dev serve
|
|
|
6405
6405
|
|
|
6406
6406
|
1. The shortcut is disarmed and the terminal handed back, so the package manager owns stdin.
|
|
6407
6407
|
2. Every `@warlock.js/*` dependency is rewritten to latest and installed — exactly what `warlock update` does.
|
|
6408
|
-
3. The worker shuts down (freeing the http port) and exits `75`; the `warlock dev` supervisor spawns a replacement on the new version. See
|
|
6408
|
+
3. The worker shuts down (freeing the http port) and exits `75`; the `warlock dev` supervisor spawns a replacement on the new version. See the `run-app` topic for the supervisor.
|
|
6409
6409
|
|
|
6410
6410
|
What happens when it doesn't go to plan:
|
|
6411
6411
|
|
|
@@ -6417,7 +6417,7 @@ What happens when it doesn't go to plan:
|
|
|
6417
6417
|
|
|
6418
6418
|
The shortcut is only offered when stdin is an interactive TTY. When it isn't (CI, piped stdin, a process supervisor), the notice falls back to the `Run npx warlock update` line instead — it never silently does nothing.
|
|
6419
6419
|
|
|
6420
|
-
`u` joins the dev server's standing shortcut bar (`r` restart, `c` clear, `q` quit, `h` help) — press `h` to list whatever is armed. See
|
|
6420
|
+
`u` joins the dev server's standing shortcut bar (`r` restart, `c` clear, `q` quit, `h` help) — press `h` to list whatever is armed. See the `run-app` topic for the bar and the raw-mode / `Ctrl+C` contract.
|
|
6421
6421
|
|
|
6422
6422
|
It is automatically skipped when:
|
|
6423
6423
|
|
|
@@ -6454,16 +6454,16 @@ Two small zero-dependency utilities back the tooling and are exported from `@war
|
|
|
6454
6454
|
|
|
6455
6455
|
## See also
|
|
6456
6456
|
|
|
6457
|
-
-
|
|
6458
|
-
-
|
|
6459
|
-
-
|
|
6457
|
+
- The `run-app` topic — `warlock dev` / `build` / `start` and the `devServer.*` config knobs.
|
|
6458
|
+
- The `write-cli-command` topic — author your own `warlock <cmd>`.
|
|
6459
|
+
- The `configure-app` topic — `warlock.config.ts` shape and `defineConfig`.
|
|
6460
6460
|
|
|
6461
6461
|
|
|
6462
6462
|
## upload-file `@warlock.js/core/upload-file/SKILL.md`
|
|
6463
6463
|
|
|
6464
6464
|
---
|
|
6465
6465
|
name: upload-file
|
|
6466
|
-
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 —
|
|
6466
|
+
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 — the `store-file` topic; image-only transforms — the `process-image` topic; schema rules — the `validate-input` topic; competing libs `multer`, `formidable`, `busboy`.'
|
|
6467
6467
|
---
|
|
6468
6468
|
|
|
6469
6469
|
# Warlock — upload a file
|
|
@@ -6671,7 +6671,7 @@ v.file() // must be UploadedFile
|
|
|
6671
6671
|
.minHeight(200).maxHeight(4000);
|
|
6672
6672
|
```
|
|
6673
6673
|
|
|
6674
|
-
Size accepts either bytes (`.maxSize(5_242_880)`) or `{ unit, size }` (`{ unit: "MB", size: 5 }`). See
|
|
6674
|
+
Size accepts either bytes (`.maxSize(5_242_880)`) or `{ unit, size }` (`{ unit: "MB", size: 5 }`). See the `validate-input` topic for the full validation pattern.
|
|
6675
6675
|
|
|
6676
6676
|
### Optional file field
|
|
6677
6677
|
|
|
@@ -6754,7 +6754,7 @@ await storage.use("s3").put(await uploadedFile.buffer(), "documents/report.pdf",
|
|
|
6754
6754
|
|
|
6755
6755
|
### Stream a download from a stored file
|
|
6756
6756
|
|
|
6757
|
-
The reverse direction — sending a stored file back via `response.sendFile(...)` is the cleanest path. For dynamic content, use `response.stream(...)`. See
|
|
6757
|
+
The reverse direction — sending a stored file back via `response.sendFile(...)` is the cleanest path. For dynamic content, use `response.stream(...)`. See the `send-response` topic.
|
|
6758
6758
|
|
|
6759
6759
|
## Gotchas
|
|
6760
6760
|
|
|
@@ -6768,17 +6768,17 @@ The reverse direction — sending a stored file back via `response.sendFile(...)
|
|
|
6768
6768
|
|
|
6769
6769
|
## See also
|
|
6770
6770
|
|
|
6771
|
-
-
|
|
6772
|
-
-
|
|
6773
|
-
-
|
|
6774
|
-
-
|
|
6771
|
+
- The `validate-input` topic — `v.file()` rules and the validation pipeline.
|
|
6772
|
+
- The `create-controller` topic — pulling files from `request.validated()` vs `request.file()`.
|
|
6773
|
+
- The `send-response` topic — `response.sendFile(...)` for serving the stored file back.
|
|
6774
|
+
- The `warlock-conventions` topic — storage configuration and driver selection.
|
|
6775
6775
|
|
|
6776
6776
|
|
|
6777
6777
|
## use-app-context `@warlock.js/core/use-app-context/SKILL.md`
|
|
6778
6778
|
|
|
6779
6779
|
---
|
|
6780
6780
|
name: use-app-context
|
|
6781
|
-
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 —
|
|
6781
|
+
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 — the `resolve-path` topic; connector start order — the `add-connector` topic; competing patterns: bare `process.env.NODE_ENV`, ad-hoc Fastify imports.'
|
|
6782
6782
|
---
|
|
6783
6783
|
|
|
6784
6784
|
# Warlock — use the application context
|
|
@@ -6909,11 +6909,11 @@ Application.onceBooted(() => {
|
|
|
6909
6909
|
|
|
6910
6910
|
Hooks run **LIFO** (reverse of registration — last opened, first closed), each is awaited, and a throwing hook is caught + logged so it can't block the rest. `Application.isShuttingDown` flips `true` the moment shutdown begins — the built-in `/ready` endpoint reads it to report not-ready so a load balancer drains the instance first. Like `onceBooted`, registering after shutdown has begun runs the callback immediately.
|
|
6911
6911
|
|
|
6912
|
-
The framework triggers this for you (the connectors manager runs the hooks at the start of shutdown); app code only ever registers via `onShutdown`. For the HTTP-side story — `/health`, `/ready`, and graceful request draining — see
|
|
6912
|
+
The framework triggers this for you (the connectors manager runs the hooks at the start of shutdown); app code only ever registers via `onShutdown`. For the HTTP-side story — `/health`, `/ready`, and graceful request draining — see the `health-checks` topic.
|
|
6913
6913
|
|
|
6914
6914
|
## Paths
|
|
6915
6915
|
|
|
6916
|
-
For path helpers (`appPath`, `configPath`, `uploadsPath`, …) anchored at `process.cwd()`, the `paths.*` aggregate, and the `uploads.root` config override, see
|
|
6916
|
+
For path helpers (`appPath`, `configPath`, `uploadsPath`, …) anchored at `process.cwd()`, the `paths.*` aggregate, and the `uploads.root` config override, see the `resolve-path` topic.
|
|
6917
6917
|
|
|
6918
6918
|
The most-used helpers are also surfaced as no-argument getters on `Application`:
|
|
6919
6919
|
|
|
@@ -7072,17 +7072,17 @@ cors: {
|
|
|
7072
7072
|
|
|
7073
7073
|
## See also
|
|
7074
7074
|
|
|
7075
|
-
-
|
|
7076
|
-
-
|
|
7077
|
-
-
|
|
7078
|
-
-
|
|
7075
|
+
- The `resolve-path` topic — path helpers (`appPath`, `configPath`, `uploadsPath`, …) and the `paths.*` aggregate.
|
|
7076
|
+
- The `configure-app` topic — `src/config/*.ts` and `warlock.config.ts`.
|
|
7077
|
+
- The `add-connector` topic — using `Application.runtimeStrategy` inside a connector's `start()`.
|
|
7078
|
+
- The `warlock-conventions` topic — module layout, where paths point to.
|
|
7079
7079
|
|
|
7080
7080
|
|
|
7081
7081
|
## use-localization `@warlock.js/core/use-localization/SKILL.md`
|
|
7082
7082
|
|
|
7083
7083
|
---
|
|
7084
7084
|
name: use-localization
|
|
7085
|
-
description: 'Multi-locale translations via `groupedTranslations` (declare keys), `t()` (look up; always use it in app code, never `request.t()`), `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 —
|
|
7085
|
+
description: 'Multi-locale translations via `groupedTranslations` (declare keys), `t()` (look up; always use it in app code, never `request.t()`), `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 — the `define-resource` topic; module scaffold — the `create-module` topic; competing libs `i18next`, `react-intl`, raw `@mongez/localization`.'
|
|
7086
7086
|
---
|
|
7087
7087
|
|
|
7088
7088
|
# Warlock — translate keys + pick localized values
|
|
@@ -7197,7 +7197,7 @@ When an app uses `@warlock.js/web`, `warlock dev` writes `.warlock/typings/trans
|
|
|
7197
7197
|
`useTrans()` now works correctly across hydration (5.15.0): the hydration
|
|
7198
7198
|
payload ships a `translations` key with the active locale's keywords, and
|
|
7199
7199
|
`@warlock.js/web` registers them into this same lookup table before the
|
|
7200
|
-
client hydrates — see
|
|
7200
|
+
client hydrates — see the `write-the-root` topic of the `warlock-js-web` skill's "`useTrans()`
|
|
7201
7201
|
survives hydration" section for the failure this fixed.
|
|
7202
7202
|
|
|
7203
7203
|
### Locale on a specific lookup
|
|
@@ -7398,10 +7398,10 @@ GET /products/42?locale=ar
|
|
|
7398
7398
|
|
|
7399
7399
|
## See also
|
|
7400
7400
|
|
|
7401
|
-
-
|
|
7402
|
-
-
|
|
7403
|
-
-
|
|
7404
|
-
-
|
|
7401
|
+
- The `send-response` topic — error helpers that pair with translated messages (`response.notFound({ error: t("...") })`).
|
|
7402
|
+
- The `define-resource` topic — using `getLocalized` inside resource output for clean per-locale responses.
|
|
7403
|
+
- The `create-module` topic — the `utils/locales.json` file is part of the generated module scaffold.
|
|
7404
|
+
- The `warlock-conventions` topic — `utils/locales.json` is auto-loaded; the suffix is mandatory.
|
|
7405
7405
|
|
|
7406
7406
|
## Route-owned web translations (5.17)
|
|
7407
7407
|
|
|
@@ -7424,7 +7424,7 @@ When a route-locales snapshot applies, `t()` (through the request binding) and `
|
|
|
7424
7424
|
|
|
7425
7425
|
---
|
|
7426
7426
|
name: use-middleware
|
|
7427
|
-
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 —
|
|
7427
|
+
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 — the `write-middleware` topic; cache singleton — the `cache-basics` topic of the `warlock-js-cache` skill; competing libs `@fastify/rate-limit` direct, `express-rate-limit`, `helmet`.'
|
|
7428
7428
|
---
|
|
7429
7429
|
|
|
7430
7430
|
# Warlock — use built-in middleware
|
|
@@ -7440,7 +7440,7 @@ middleware.maxBodySize("2mb");
|
|
|
7440
7440
|
// ... etc
|
|
7441
7441
|
```
|
|
7442
7442
|
|
|
7443
|
-
For authoring your OWN middleware (custom guards, enrichment, etc.), see
|
|
7443
|
+
For authoring your OWN middleware (custom guards, enrichment, etc.), see the `write-middleware` topic.
|
|
7444
7444
|
|
|
7445
7445
|
## The catalog
|
|
7446
7446
|
|
|
@@ -7692,17 +7692,17 @@ export default {
|
|
|
7692
7692
|
|
|
7693
7693
|
## See also
|
|
7694
7694
|
|
|
7695
|
-
-
|
|
7696
|
-
-
|
|
7697
|
-
-
|
|
7698
|
-
-
|
|
7695
|
+
- The `write-middleware` topic — author your OWN middleware (custom guards, enrichment).
|
|
7696
|
+
- The `register-route` topic — where middleware attaches: `router.group` and route-options.
|
|
7697
|
+
- The `send-response` topic — the response helpers used to short-circuit (`tooManyRequests`, `contentTooLarge`, `serviceUnavailable`, etc.).
|
|
7698
|
+
- The `cache-basics` topic of the `warlock-js-cache` skill — the cache singleton (`@warlock.js/cache`) that backs `middleware.idempotency` and `middleware.cache`.
|
|
7699
7699
|
|
|
7700
7700
|
|
|
7701
7701
|
## use-model-transformers `@warlock.js/core/use-model-transformers/SKILL.md`
|
|
7702
7702
|
|
|
7703
7703
|
---
|
|
7704
7704
|
name: use-model-transformers
|
|
7705
|
-
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 —
|
|
7705
|
+
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 — the `hash-password` topic; repository writes — the `use-repository` topic; output filtering — the `define-resource` topic; competing patterns: manual `await hashPassword(input)` in services, ORM lifecycle hooks.'
|
|
7706
7706
|
---
|
|
7707
7707
|
|
|
7708
7708
|
# Warlock — declare model transformers
|
|
@@ -7762,7 +7762,7 @@ What it does at save time:
|
|
|
7762
7762
|
| Existing row, password unchanged | Pass through (no re-hashing — stored hash preserved). |
|
|
7763
7763
|
| Empty / undefined value | Pass through untouched. |
|
|
7764
7764
|
|
|
7765
|
-
Calls `authService.hashPassword(String(value))` under the hood — same bcryptjs path as the standalone `hashPassword()` helper. See
|
|
7765
|
+
Calls `authService.hashPassword(String(value))` under the hood — same bcryptjs path as the standalone `hashPassword()` helper. See the `hash-password` topic for full bcrypt setup (salt rounds, `npm install bcryptjs`).
|
|
7766
7766
|
|
|
7767
7767
|
### Why declarative wins
|
|
7768
7768
|
|
|
@@ -7916,17 +7916,17 @@ Rule of thumb: transformers are for **pure, deterministic** transforms of the ro
|
|
|
7916
7916
|
|
|
7917
7917
|
## See also
|
|
7918
7918
|
|
|
7919
|
-
-
|
|
7920
|
-
-
|
|
7921
|
-
-
|
|
7922
|
-
-
|
|
7919
|
+
- The `hash-password` topic — the bcrypt setup that `useHashedPassword` calls under the hood; salt rounds, `npm install bcryptjs`.
|
|
7920
|
+
- The `use-repository` topic — where `create` / `save` calls happen that trigger the transformers.
|
|
7921
|
+
- The `define-resource` topic — filtering transformed fields (`password`) out of API responses.
|
|
7922
|
+
- The `warlock-conventions` topic — schema files live in `src/app/<module>/models/<entity>/<entity>.model.ts`.
|
|
7923
7923
|
|
|
7924
7924
|
|
|
7925
7925
|
## use-repository `@warlock.js/core/use-repository/SKILL.md`
|
|
7926
7926
|
|
|
7927
7927
|
---
|
|
7928
7928
|
name: use-repository
|
|
7929
|
-
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 —
|
|
7929
|
+
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 — the `cache-basics` topic of the `warlock-js-cache` skill; use-case pipelines — the `write-use-case` topic; wire mapping — the `define-resource` topic; competing libs `typeorm` Repository, `prisma.client.<model>`, `@nestjs/typeorm`.'
|
|
7930
7930
|
---
|
|
7931
7931
|
|
|
7932
7932
|
# Warlock — use a repository
|
|
@@ -8348,19 +8348,19 @@ The third arg is a context object — `{ allValues, dateFormat, ... }` — for f
|
|
|
8348
8348
|
|
|
8349
8349
|
## See also
|
|
8350
8350
|
|
|
8351
|
-
-
|
|
8352
|
-
-
|
|
8353
|
-
-
|
|
8354
|
-
-
|
|
8355
|
-
-
|
|
8356
|
-
-
|
|
8351
|
+
- The `create-module` topic — `warlock generate.repository` and where the file lives.
|
|
8352
|
+
- The `cache-basics` topic of the `warlock-js-cache` skill — the cache singleton behind `listCached` / `getCached`. See sibling skills (`pick-cache-driver`, `use-swr`) for related tasks.
|
|
8353
|
+
- The `write-use-case` topic — calling repositories from a use-case handler.
|
|
8354
|
+
- The `define-resource` topic — mapping repository output to the wire format.
|
|
8355
|
+
- The `create-controller` topic — services that consume repositories from the controller edge.
|
|
8356
|
+
- The `warlock-conventions` topic — controller → service → repository → model layering.
|
|
8357
8357
|
|
|
8358
8358
|
|
|
8359
8359
|
## use-request-locals `@warlock.js/core/use-request-locals/SKILL.md`
|
|
8360
8360
|
|
|
8361
8361
|
---
|
|
8362
8362
|
name: use-request-locals
|
|
8363
|
-
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` —
|
|
8363
|
+
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` — the `request-memo` topic; middleware mechanics — the `write-middleware` topic; authenticated user typing — augment `RequestUser`, not `RequestLocals`; competing patterns: `(request as any).foo`, `request.set()`, module-global mutable state.'
|
|
8364
8364
|
---
|
|
8365
8365
|
|
|
8366
8366
|
# Warlock — use typed request locals
|
|
@@ -8522,16 +8522,16 @@ Writing `request.locals.organization` does not affect `request.all()`, `request.
|
|
|
8522
8522
|
|
|
8523
8523
|
## See also
|
|
8524
8524
|
|
|
8525
|
-
-
|
|
8526
|
-
-
|
|
8527
|
-
-
|
|
8525
|
+
- The `request-memo` topic — the `fromRequest()` migration and single-flight request memoization.
|
|
8526
|
+
- The `write-middleware` topic — middleware execution and registration.
|
|
8527
|
+
- The `create-controller` topic — reading locals in downstream controllers.
|
|
8528
8528
|
|
|
8529
8529
|
|
|
8530
8530
|
## validate-input `@warlock.js/core/validate-input/SKILL.md`
|
|
8531
8531
|
|
|
8532
8532
|
---
|
|
8533
8533
|
name: validate-input
|
|
8534
|
-
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 —
|
|
8534
|
+
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 — the `seal-basics` topic of the `warlock-js-seal` skill; controller wiring — the `create-controller` topic; file rules deep-dive — the `upload-file` topic; competing libs `zod`, `joi`, `yup`, `class-validator`.'
|
|
8535
8535
|
---
|
|
8536
8536
|
|
|
8537
8537
|
# Warlock — validate a request
|
|
@@ -8604,7 +8604,7 @@ From `@warlock.js/seal` — **always import from seal directly**. `@warlock.js/c
|
|
|
8604
8604
|
| `v.literal(...values)` | exact literals | — |
|
|
8605
8605
|
| `v.instanceof(Ctor, msg?)` | `Ctor` instances | — |
|
|
8606
8606
|
| `v.lazy(() => schema)` | recursive/forward refs | — |
|
|
8607
|
-
| `v.file(msg?)` | `UploadedFile` | `.image()`, `.accept(exts)`, `.mimeType(types)`, `.minSize(n)`, `.maxSize(n)`, `.minWidth(n)`, `.maxWidth(n)` — see
|
|
8607
|
+
| `v.file(msg?)` | `UploadedFile` | `.image()`, `.accept(exts)`, `.mimeType(types)`, `.minSize(n)`, `.maxSize(n)`, `.minWidth(n)`, `.maxWidth(n)` — see the `upload-file` topic |
|
|
8608
8608
|
| `v.computed(callback)` | derived value | — |
|
|
8609
8609
|
| `v.managed(callback)` | framework-injected value | — |
|
|
8610
8610
|
|
|
@@ -8699,7 +8699,7 @@ const uploadAvatarSchema = v.object({
|
|
|
8699
8699
|
});
|
|
8700
8700
|
```
|
|
8701
8701
|
|
|
8702
|
-
Full file chain: `.image()`, `.accept(extensions)`, `.mimeType(types)`, `.pdf()`, `.excel()`, `.word()`, `.minSize(n)`, `.maxSize(n)`, `.minWidth(px)`, `.maxWidth(px)`, `.minHeight(px)`, `.maxHeight(px)`. See
|
|
8702
|
+
Full file chain: `.image()`, `.accept(extensions)`, `.mimeType(types)`, `.pdf()`, `.excel()`, `.word()`, `.minSize(n)`, `.maxSize(n)`, `.minWidth(px)`, `.maxWidth(px)`, `.minHeight(px)`, `.maxHeight(px)`. See the `upload-file` topic for the full upload flow.
|
|
8703
8703
|
|
|
8704
8704
|
### Optional file field
|
|
8705
8705
|
|
|
@@ -8835,17 +8835,17 @@ updateProductController.validation = {
|
|
|
8835
8835
|
|
|
8836
8836
|
## See also
|
|
8837
8837
|
|
|
8838
|
-
-
|
|
8839
|
-
-
|
|
8840
|
-
-
|
|
8841
|
-
-
|
|
8838
|
+
- The `create-controller` topic — how the schema attaches and how `request.validated()` reads.
|
|
8839
|
+
- The `upload-file` topic — `v.file()` and how it interacts with multipart uploads.
|
|
8840
|
+
- The `send-response` topic — the 400 helper used internally by `failedSchema`.
|
|
8841
|
+
- The `warlock-conventions` topic — `Request<Schema>` type-alias convention.
|
|
8842
8842
|
|
|
8843
8843
|
|
|
8844
8844
|
## warlock-conventions `@warlock.js/core/warlock-conventions/SKILL.md`
|
|
8845
8845
|
|
|
8846
8846
|
---
|
|
8847
8847
|
name: warlock-conventions
|
|
8848
|
-
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 —
|
|
8848
|
+
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 — the `create-module` topic; route shape — the `register-route` topic; controller shape — the `create-controller` topic; competing patterns: `express` ad-hoc layouts, `@nestjs/common` decorator-driven structure.'
|
|
8849
8849
|
---
|
|
8850
8850
|
|
|
8851
8851
|
# Warlock — framework-wide conventions
|
|
@@ -8969,24 +8969,24 @@ Within the same module, use relative paths (`./`, `../`).
|
|
|
8969
8969
|
|
|
8970
8970
|
## Type augmentations
|
|
8971
8971
|
|
|
8972
|
-
`src/typings.d.ts` is the project's module-augmentation file. It ships with the scaffold, is listed explicitly in `tsconfig.json`'s `include`, and is where application-wide `declare module "@warlock.js/core"` blocks live — `RequestLocals` and `RequestUser` are already there as empty interfaces. Keep its trailing `export {}` (without it the block declares an ambient module and erases the framework's real typings) and keep the augmented declarations as `interface`, the one sanctioned exception to this project's prefer-`type` rule, since declaration merging is interface-only. See
|
|
8972
|
+
`src/typings.d.ts` is the project's module-augmentation file. It ships with the scaffold, is listed explicitly in `tsconfig.json`'s `include`, and is where application-wide `declare module "@warlock.js/core"` blocks live — `RequestLocals` and `RequestUser` are already there as empty interfaces. Keep its trailing `export {}` (without it the block declares an ambient module and erases the framework's real typings) and keep the augmented declarations as `interface`, the one sanctioned exception to this project's prefer-`type` rule, since declaration merging is interface-only. See the `use-request-locals` topic.
|
|
8973
8973
|
|
|
8974
8974
|
## Decorators
|
|
8975
8975
|
|
|
8976
|
-
Cascade uses `@RegisterModel()` for the model registry and `@BelongsTo` / `@HasMany` / `@MorphTo` for relations. The scaffolded `tsconfig.json` has `"experimentalDecorators": false` — these are native Stage-3 decorators, not legacy. Never set that flag to `true`; see
|
|
8976
|
+
Cascade uses `@RegisterModel()` for the model registry and `@BelongsTo` / `@HasMany` / `@MorphTo` for relations. The scaffolded `tsconfig.json` has `"experimentalDecorators": false` — these are native Stage-3 decorators, not legacy. Never set that flag to `true`; see the `lower-stage3-decorators` topic.
|
|
8977
8977
|
|
|
8978
8978
|
## See also
|
|
8979
8979
|
|
|
8980
|
-
-
|
|
8981
|
-
-
|
|
8982
|
-
-
|
|
8980
|
+
- The `register-route` topic — how to wire URLs to controllers.
|
|
8981
|
+
- The `create-controller` topic — controller signature, validation, response shape.
|
|
8982
|
+
- The `send-response` topic — the full Response helper surface.
|
|
8983
8983
|
|
|
8984
8984
|
|
|
8985
8985
|
## warlock-doctor `@warlock.js/core/warlock-doctor/SKILL.md`
|
|
8986
8986
|
|
|
8987
8987
|
---
|
|
8988
8988
|
name: warlock-doctor
|
|
8989
|
-
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 —
|
|
8989
|
+
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 — the `health-checks` topic; authoring a general CLI command — the `write-cli-command` topic; releasing the package — `releasing-warlock-monorepo`; competing tools `npm doctor`, `nest info`, hand-rolled preflight scripts.'
|
|
8990
8990
|
---
|
|
8991
8991
|
|
|
8992
8992
|
# Warlock — `warlock doctor`
|
|
@@ -9118,22 +9118,22 @@ A `⚠ routes: 0 routes registered` line is the tell that a route module threw o
|
|
|
9118
9118
|
|
|
9119
9119
|
## See also
|
|
9120
9120
|
|
|
9121
|
-
-
|
|
9122
|
-
-
|
|
9123
|
-
-
|
|
9124
|
-
-
|
|
9121
|
+
- The `health-checks` topic — the live `/health` + `/ready` HTTP probes and the `health` registry the `health` doctor check reports on.
|
|
9122
|
+
- The `write-cli-command` topic — authoring a command + its `preload` plan, the shape `doctorCommand` is built from.
|
|
9123
|
+
- The `add-connector` topic — connector registration, which the `connectors` check enumerates.
|
|
9124
|
+
- The `warlock-conventions` topic — project layout the checks assume.
|
|
9125
9125
|
|
|
9126
9126
|
|
|
9127
9127
|
## warlock-routes `@warlock.js/core/warlock-routes/SKILL.md`
|
|
9128
9128
|
|
|
9129
9129
|
---
|
|
9130
9130
|
name: warlock-routes
|
|
9131
|
-
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 —
|
|
9131
|
+
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 — the `warlock-doctor` topic; defining/naming/grouping routes — the `register-route` topic; authoring a general CLI command — the `write-cli-command` topic; competing tools `nest`/`express` route listers, `php artisan route:list`.'
|
|
9132
9132
|
---
|
|
9133
9133
|
|
|
9134
9134
|
# Warlock — `warlock routes`
|
|
9135
9135
|
|
|
9136
|
-
`warlock routes` lists every registered HTTP route as a table. It's the read-only sibling of
|
|
9136
|
+
`warlock routes` lists every registered HTTP route as a table. It's the read-only sibling of the `warlock-doctor` topic: it boots the app far enough to register route modules — but **starts no connectors**, so it never opens a database, cache, or socket connection.
|
|
9137
9137
|
|
|
9138
9138
|
```bash
|
|
9139
9139
|
npx warlock routes
|
|
@@ -9251,17 +9251,17 @@ and exits non-zero.
|
|
|
9251
9251
|
|
|
9252
9252
|
## See also
|
|
9253
9253
|
|
|
9254
|
-
-
|
|
9255
|
-
-
|
|
9256
|
-
-
|
|
9257
|
-
-
|
|
9254
|
+
- The `warlock-doctor` topic — the read-only diagnostics sibling; its `routes` check warns when this table would be empty.
|
|
9255
|
+
- The `register-route` topic — defining, naming, and grouping the routes this command lists.
|
|
9256
|
+
- The `run-app` topic — `warlock build`, the command that produces the snapshot `routes:diff` compares against.
|
|
9257
|
+
- The `write-cli-command` topic — the command + `preload` shape `routesCommand` is built from.
|
|
9258
9258
|
|
|
9259
9259
|
|
|
9260
9260
|
## wire-socket `@warlock.js/core/wire-socket/SKILL.md`
|
|
9261
9261
|
|
|
9262
9262
|
---
|
|
9263
9263
|
name: wire-socket
|
|
9264
|
-
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 —
|
|
9264
|
+
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 — the `add-connector` topic; app context accessors — the `use-app-context` topic; competing libs `ws`, `socket.io` direct without Warlock connector, `uWebSockets.js`.'
|
|
9265
9265
|
---
|
|
9266
9266
|
|
|
9267
9267
|
# Warlock — wire a Socket.IO server
|
|
@@ -9544,16 +9544,16 @@ CLI commands, scheduled jobs, queue workers — anything running outside an HTTP
|
|
|
9544
9544
|
|
|
9545
9545
|
## See also
|
|
9546
9546
|
|
|
9547
|
-
-
|
|
9548
|
-
-
|
|
9549
|
-
-
|
|
9547
|
+
- The `use-app-context` topic — `app.socket` runtime accessor + `Application` static metadata.
|
|
9548
|
+
- The `add-connector` topic — how connectors order their boot sequence around your modules.
|
|
9549
|
+
- The `warlock-conventions` topic — where socket-related code lives (a setup function for handler registration, `services/` for emit sites).
|
|
9550
9550
|
|
|
9551
9551
|
|
|
9552
9552
|
## write-cli-command `@warlock.js/core/write-cli-command/SKILL.md`
|
|
9553
9553
|
|
|
9554
9554
|
---
|
|
9555
9555
|
name: write-cli-command
|
|
9556
|
-
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 —
|
|
9556
|
+
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 — the `run-app` topic; warlock.config.ts wiring — the `configure-app` topic; competing libs `commander`, `yargs`, `oclif`.'
|
|
9557
9557
|
---
|
|
9558
9558
|
|
|
9559
9559
|
# Warlock — write a CLI command
|
|
@@ -9703,7 +9703,7 @@ console.log(colors.green("✓") + " user promoted");
|
|
|
9703
9703
|
|
|
9704
9704
|
The framework ships a fixed set of commands you call but don't author. Knowing their flags up front saves a `--help` round-trip.
|
|
9705
9705
|
|
|
9706
|
-
> For `warlock dev` / `warlock build` / `warlock start` — see
|
|
9706
|
+
> For `warlock dev` / `warlock build` / `warlock start` — see the `run-app` topic. Everything below covers the rest.
|
|
9707
9707
|
|
|
9708
9708
|
### Database + migrations
|
|
9709
9709
|
|
|
@@ -9749,7 +9749,7 @@ warlock generate.typings
|
|
|
9749
9749
|
warlock generate (alias: g) — interactive picker
|
|
9750
9750
|
```
|
|
9751
9751
|
|
|
9752
|
-
`<m>/<n>` is `<module>/<name>` (e.g. `products/create-product`). See
|
|
9752
|
+
`<m>/<n>` is `<module>/<name>` (e.g. `products/create-product`). See the `create-module` topic for the full scaffolding flow.
|
|
9753
9753
|
|
|
9754
9754
|
### Feature installation
|
|
9755
9755
|
|
|
@@ -9864,16 +9864,16 @@ export default command({
|
|
|
9864
9864
|
|
|
9865
9865
|
## See also
|
|
9866
9866
|
|
|
9867
|
-
-
|
|
9868
|
-
-
|
|
9869
|
-
-
|
|
9867
|
+
- The `run-app` topic — the operational commands (`dev` / `build` / `start`) with all flags and config knobs.
|
|
9868
|
+
- The `configure-app` topic — wiring `defineConfig` and `warlock.config.ts`.
|
|
9869
|
+
- The `warlock-conventions` topic — module layout, canonical imports.
|
|
9870
9870
|
|
|
9871
9871
|
|
|
9872
9872
|
## write-middleware `@warlock.js/core/write-middleware/SKILL.md`
|
|
9873
9873
|
|
|
9874
9874
|
---
|
|
9875
9875
|
name: write-middleware
|
|
9876
|
-
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 —
|
|
9876
|
+
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 — the `use-middleware` topic; route attachment — the `register-route` topic; response helpers — the `send-response` topic; competing patterns: `express` `(req, res, next)` middleware, Fastify `preHandler` hooks.'
|
|
9877
9877
|
---
|
|
9878
9878
|
|
|
9879
9879
|
# Warlock — write a middleware
|
|
@@ -9924,7 +9924,7 @@ export const requireFeatureFlag: Middleware = async ({ request, response }) => {
|
|
|
9924
9924
|
};
|
|
9925
9925
|
```
|
|
9926
9926
|
|
|
9927
|
-
If you short-circuit, the controller never runs. The response helper you pick (`forbidden`, `unauthorized`, `badRequest`, etc.) sets the status — see
|
|
9927
|
+
If you short-circuit, the controller never runs. The response helper you pick (`forbidden`, `unauthorized`, `badRequest`, etc.) sets the status — see the `send-response` topic.
|
|
9928
9928
|
|
|
9929
9929
|
## Enriching the request
|
|
9930
9930
|
|
|
@@ -10073,7 +10073,7 @@ export const optionalAuth: Middleware = async ({ request, response }) => {
|
|
|
10073
10073
|
|
|
10074
10074
|
## Using built-in middleware
|
|
10075
10075
|
|
|
10076
|
-
`@warlock.js/core` ships seven built-in middlewares (rate limit, concurrency cap, body cap, idempotency, maintenance, IP filter, response cache) under the `middleware` namespace from `@warlock.js/core`. They cover the patterns most apps need — see
|
|
10076
|
+
`@warlock.js/core` ships seven built-in middlewares (rate limit, concurrency cap, body cap, idempotency, maintenance, IP filter, response cache) under the `middleware` namespace from `@warlock.js/core`. They cover the patterns most apps need — see the `use-middleware` topic for the catalog, per-primitive deep-dives, error semantics, and gotchas specific to using them.
|
|
10077
10077
|
|
|
10078
10078
|
`X-Request-Id` correlation is wired automatically (inherit + echo on every response) — the same skill covers that too. It's not a middleware; nothing to register.
|
|
10079
10079
|
|
|
@@ -10090,18 +10090,18 @@ export const optionalAuth: Middleware = async ({ request, response }) => {
|
|
|
10090
10090
|
|
|
10091
10091
|
## See also
|
|
10092
10092
|
|
|
10093
|
-
-
|
|
10094
|
-
-
|
|
10095
|
-
-
|
|
10096
|
-
-
|
|
10097
|
-
-
|
|
10093
|
+
- The `use-middleware` topic — the built-in middleware catalog (`rateLimit`, `idempotency`, `maxBodySize`, etc.) + request-id correlation.
|
|
10094
|
+
- The `register-route` topic — where middleware attaches: `router.group` and route-options.
|
|
10095
|
+
- The `create-controller` topic — how the controller picks up `request.locals.user`, `request.validated()`, etc., set by upstream middleware.
|
|
10096
|
+
- The `send-response` topic — the response helpers used to short-circuit.
|
|
10097
|
+
- The `warlock-conventions` topic — the `guarded()` / `guardedAdmin()` / `publicRoutes()` convention.
|
|
10098
10098
|
|
|
10099
10099
|
|
|
10100
10100
|
## write-seeder `@warlock.js/core/write-seeder/SKILL.md`
|
|
10101
10101
|
|
|
10102
10102
|
---
|
|
10103
10103
|
name: write-seeder
|
|
10104
|
-
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 —
|
|
10104
|
+
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 — the `create-module` topic; repository CRUD — the `use-repository` topic; CLI flags — the `write-cli-command` topic; competing patterns: hand-rolled `node scripts/seed.js`, `typeorm-seeding`.'
|
|
10105
10105
|
---
|
|
10106
10106
|
|
|
10107
10107
|
# Warlock — write a seeder
|
|
@@ -10472,17 +10472,17 @@ warlock seed --transaction # (default true) — pass --transaction=false to s
|
|
|
10472
10472
|
|
|
10473
10473
|
## See also
|
|
10474
10474
|
|
|
10475
|
-
-
|
|
10476
|
-
-
|
|
10477
|
-
-
|
|
10478
|
-
-
|
|
10475
|
+
- The `create-module` topic — the `seeds/` folder layout in a module, `generate.module` scaffolding.
|
|
10476
|
+
- The `use-repository` topic — the model `create` / `first` calls used inside seeds.
|
|
10477
|
+
- The `write-cli-command` topic — the `warlock seed` CLI flags and full preload shape.
|
|
10478
|
+
- The `warlock-conventions` topic — `seeds/` is the canonical folder name (singular `seed/` is incorrect).
|
|
10479
10479
|
|
|
10480
10480
|
|
|
10481
10481
|
## write-use-case `@warlock.js/core/write-use-case/SKILL.md`
|
|
10482
10482
|
|
|
10483
10483
|
---
|
|
10484
10484
|
name: write-use-case
|
|
10485
|
-
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 —
|
|
10485
|
+
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 — the `create-controller` topic; schema details — the `validate-input` topic; the standalone retry util — the `retry-operation` topic; competing libs `@nestjs/cqrs`, `inversify`, hand-rolled service classes.'
|
|
10486
10486
|
---
|
|
10487
10487
|
|
|
10488
10488
|
# Warlock — write a use case
|
|
@@ -10772,8 +10772,8 @@ For the plain-function flavour (`warlock generate.use-case <module>/<verb-noun>`
|
|
|
10772
10772
|
|
|
10773
10773
|
## See also
|
|
10774
10774
|
|
|
10775
|
-
-
|
|
10776
|
-
-
|
|
10775
|
+
- The `create-controller` topic — the usual next step: invoke this use case from an HTTP controller.
|
|
10776
|
+
- The `publish-message` topic of the `warlock-js-herald` skill — the message bus the `broadcast` adapter publishes to (cross-package).
|
|
10777
10777
|
|
|
10778
10778
|
|
|
10779
10779
|
|