@warlock.js/core 5.4.0 → 5.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/esm/application/app.d.mts.map +1 -1
- package/esm/application/app.mjs +7 -1
- package/esm/application/app.mjs.map +1 -1
- package/esm/cli/cli-commands.utils.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/optional-peers.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/column-dsl-parser.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/migration.generator.mjs.map +1 -1
- package/esm/cli/commands/routes/format-routes-table.mjs.map +1 -1
- package/esm/cli/commands/routes/route-row.mjs.map +1 -1
- package/esm/cli/commands/routes.command.mjs.map +1 -1
- package/esm/cli/framework-cli-commands.mjs.map +1 -1
- package/esm/config/locale-configuration.mjs +11 -1
- package/esm/config/locale-configuration.mjs.map +1 -1
- package/esm/container/container-instance-registry.mjs +40 -0
- package/esm/container/container-instance-registry.mjs.map +1 -0
- package/esm/container/index.d.mts +11 -0
- package/esm/container/index.d.mts.map +1 -1
- package/esm/container/index.mjs +11 -0
- package/esm/container/index.mjs.map +1 -1
- package/esm/database/drop-tables-action.mjs.map +1 -1
- package/esm/database/migrate-action.mjs.map +1 -1
- package/esm/database/seed-command-action.mjs.map +1 -1
- package/esm/dev-server/dependency-graph.d.mts.map +1 -1
- package/esm/dev-server/dependency-graph.mjs.map +1 -1
- package/esm/dev-server/dev-logger.mjs.map +1 -1
- package/esm/dev-server/file-event-handler.mjs.map +1 -1
- package/esm/dev-server/layer-executor.mjs.map +1 -1
- package/esm/dev-server/loader/build-transpile-init.mjs.map +1 -1
- package/esm/dev-server/loader/load-hook.mjs.map +1 -1
- package/esm/dev-server/loader/register-loader.mjs.map +1 -1
- package/esm/dev-server/loader/resolve-hook.mjs.map +1 -1
- package/esm/dev-server/loader/transpile-cache.mjs.map +1 -1
- package/esm/dev-server/module-loader.mjs.map +1 -1
- package/esm/dev-server/parse-imports.mjs.map +1 -1
- package/esm/dev-server/type-generator.mjs.map +1 -1
- package/esm/dev-server/types.d.mts.map +1 -1
- package/esm/dev-server/utils.mjs.map +1 -1
- package/esm/errors/container-key-missing-error.mjs +28 -0
- package/esm/errors/container-key-missing-error.mjs.map +1 -0
- package/esm/errors/unknown-locale-error.mjs +28 -0
- package/esm/errors/unknown-locale-error.mjs.map +1 -0
- package/esm/generations/add-command.action.mjs.map +1 -1
- package/esm/generations/features/access.feature.mjs.map +1 -1
- package/esm/generations/features/ai-anthropic.feature.mjs.map +1 -1
- package/esm/generations/features/ai-bedrock.feature.mjs.map +1 -1
- package/esm/generations/features/ai-google.feature.mjs.map +1 -1
- package/esm/generations/features/ai-ollama.feature.mjs.map +1 -1
- package/esm/generations/features/ai-openai.feature.mjs.map +1 -1
- package/esm/generations/features/ai-panoptic.feature.mjs.map +1 -1
- package/esm/generations/features/ai-tools.feature.mjs.map +1 -1
- package/esm/generations/features/ai-workspace.feature.mjs.map +1 -1
- package/esm/generations/features/ai.feature.mjs.map +1 -1
- package/esm/generations/features/herald.feature.mjs.map +1 -1
- package/esm/generations/features/notifications.feature.mjs.map +1 -1
- package/esm/generations/features/scheduler.feature.mjs.map +1 -1
- package/esm/generations/features/shared/patch-tsconfig-include.mjs.map +1 -1
- package/esm/generations/features/shared/resolve-contact-scaffold.mjs +45 -0
- package/esm/generations/features/shared/resolve-contact-scaffold.mjs.map +1 -0
- package/esm/generations/features/tailwind.feature.mjs.map +1 -1
- package/esm/generations/features/types.mjs.map +1 -1
- package/esm/generations/features/web.feature.mjs +14 -4
- package/esm/generations/features/web.feature.mjs.map +1 -1
- package/esm/http/context/request-memo.mjs.map +1 -1
- package/esm/http/middleware/cache-response-middleware.d.mts.map +1 -1
- package/esm/http/middleware/cache-response-middleware.mjs.map +1 -1
- package/esm/http/middleware/concurrency-limit.middleware.mjs.map +1 -1
- package/esm/http/middleware/idempotency.middleware.d.mts.map +1 -1
- package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
- package/esm/http/middleware/maintenance.middleware.mjs.map +1 -1
- package/esm/http/middleware/max-body-size.middleware.mjs.map +1 -1
- package/esm/http/middleware/rate-limit.middleware.mjs.map +1 -1
- package/esm/http/port-preflight.d.mts.map +1 -1
- package/esm/http/port-preflight.mjs.map +1 -1
- package/esm/http/request.d.mts.map +1 -1
- package/esm/http/request.mjs +2 -2
- package/esm/http/request.mjs.map +1 -1
- package/esm/http/response.d.mts +38 -0
- package/esm/http/response.d.mts.map +1 -1
- package/esm/http/response.mjs +47 -0
- package/esm/http/response.mjs.map +1 -1
- package/esm/http/server.d.mts.map +1 -1
- package/esm/http/server.mjs.map +1 -1
- package/esm/http/types.d.mts.map +1 -1
- package/esm/image/image.d.mts.map +1 -1
- package/esm/image/image.mjs.map +1 -1
- package/esm/mail/send-mail.mjs.map +1 -1
- package/esm/production/build-contributions.mjs.map +1 -1
- package/esm/production/bundle-framework-dependencies.mjs +152 -0
- package/esm/production/bundle-framework-dependencies.mjs.map +1 -0
- package/esm/production/production-builder.mjs +30 -3
- package/esm/production/production-builder.mjs.map +1 -1
- package/esm/production/production-supervisor.mjs.map +1 -1
- package/esm/production/tsconfig-path-aliases.mjs +99 -0
- package/esm/production/tsconfig-path-aliases.mjs.map +1 -0
- package/esm/react/index.d.mts.map +1 -1
- package/esm/react/index.mjs.map +1 -1
- package/esm/repositories/contracts/query-builder.contract.d.mts.map +1 -1
- package/esm/repositories/contracts/types.d.mts.map +1 -1
- package/esm/resource/resource-field-builder.d.mts.map +1 -1
- package/esm/resource/resource-field-builder.mjs.map +1 -1
- package/esm/resource/types.d.mts.map +1 -1
- package/esm/router/router.d.mts.map +1 -1
- package/esm/router/router.mjs +1 -2
- package/esm/router/router.mjs.map +1 -1
- package/esm/router/types.d.mts.map +1 -1
- package/esm/storage/drivers/cloud-driver.d.mts.map +1 -1
- package/esm/storage/drivers/cloud-driver.mjs.map +1 -1
- package/esm/storage/scoped-storage.d.mts.map +1 -1
- package/esm/storage/scoped-storage.mjs.map +1 -1
- package/esm/storage/storage.d.mts.map +1 -1
- package/esm/storage/storage.mjs.map +1 -1
- package/esm/storage/types.d.mts.map +1 -1
- package/esm/storage/utils/contain-path.mjs.map +1 -1
- package/esm/storage/utils/safe-fetch.d.mts.map +1 -1
- package/esm/storage/utils/safe-fetch.mjs.map +1 -1
- package/esm/tests/start-http-development-server.d.mts.map +1 -1
- package/esm/tests/start-http-development-server.mjs.map +1 -1
- package/esm/tests/test-lifecycle-state.mjs.map +1 -1
- package/esm/tests/test-setup-timeout.mjs.map +1 -1
- package/esm/tests/vitest-setup.d.mts.map +1 -1
- package/esm/tests/vitest-setup.mjs.map +1 -1
- package/esm/use-cases/use-cases-registry.d.mts.map +1 -1
- package/esm/use-cases/use-cases-registry.mjs.map +1 -1
- package/esm/utils/app-log.mjs.map +1 -1
- package/esm/utils/queue.mjs.map +1 -1
- package/esm/utils/sleep.mjs.map +1 -1
- package/esm/validation/plugins/database-plugin.mjs.map +1 -1
- package/llms-full.txt +60 -60
- package/llms.txt +3 -3
- package/package.json +12 -12
- package/skills/create-controller/SKILL.md +1 -1
- package/skills/create-module/SKILL.md +11 -11
- package/skills/hash-password/SKILL.md +4 -4
- package/skills/run-app/SKILL.md +16 -16
- package/skills/send-mail/SKILL.md +2 -2
- package/skills/use-model-transformers/SKILL.md +2 -2
- package/skills/use-repository/SKILL.md +1 -1
- package/skills/validate-input/SKILL.md +1 -1
- package/skills/warlock-doctor/SKILL.md +3 -3
- package/skills/warlock-routes/SKILL.md +10 -10
- package/skills/write-cli-command/SKILL.md +1 -1
- package/skills/write-seeder/SKILL.md +8 -8
package/llms-full.txt
CHANGED
|
@@ -1235,7 +1235,7 @@ That's the full contract. The `RequestHandler` annotation carries both parameter
|
|
|
1235
1235
|
- File: `src/app/<module>/controllers/<action>.controller.ts`.
|
|
1236
1236
|
- Export name matches the action in camelCase + `Controller` suffix: `listProductsController`, `createProductController`, `getProductController`.
|
|
1237
1237
|
|
|
1238
|
-
Scaffold with: `
|
|
1238
|
+
Scaffold with: `npx warlock generate.controller <module>/<action>` (add `--with-validation` to get the schema generated alongside).
|
|
1239
1239
|
|
|
1240
1240
|
## Reading input
|
|
1241
1241
|
|
|
@@ -1437,7 +1437,7 @@ No `if (!product)` branch in the controller. The error class carries the HTTP se
|
|
|
1437
1437
|
|
|
1438
1438
|
---
|
|
1439
1439
|
name: create-module
|
|
1440
|
-
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 `
|
|
1440
|
+
description: 'Scaffold a new feature module under `src/app/<name>/` via `warlock generate.module` and the follow-up generators for controllers, models, repositories, resources, and validation schemas. Triggers: `warlock generate.module`, `generate.controller`, `generate.service`, `generate.model`, `generate.repository`, `generate.resource`, `generate.migration`, `--minimal`, `gen.m`; "scaffold a new module", "create CRUD bootstrap", "add a controller to a module", "generate a model"; typical CLI `npx warlock generate.module <name>`. Skip: framework-wide layout rules — `@warlock.js/core/warlock-conventions/SKILL.md`; routes file shape — `@warlock.js/core/register-route/SKILL.md`; controller shape — `@warlock.js/core/create-controller/SKILL.md`; competing tooling: `@nestjs/cli`, `hygen`, hand-rolled folder layouts.'
|
|
1441
1441
|
---
|
|
1442
1442
|
|
|
1443
1443
|
# Warlock — create a module
|
|
@@ -1447,8 +1447,8 @@ A module is a self-contained feature folder under `src/app/<name>/`. The CLI sca
|
|
|
1447
1447
|
## The shape
|
|
1448
1448
|
|
|
1449
1449
|
```bash
|
|
1450
|
-
|
|
1451
|
-
|
|
1450
|
+
npx warlock generate.module products # full CRUD bootstrap (default — controllers, model, services, repository, resource, schemas, routes, seed)
|
|
1451
|
+
npx warlock generate.module products --minimal # bare bones (routes.ts + main.ts + utils/locales.ts + empty subfolders)
|
|
1452
1452
|
```
|
|
1453
1453
|
|
|
1454
1454
|
Full CRUD is the default — opt down to a bare skeleton with `--minimal` (`-m`) when you want to build the module piece by piece. `--force` (`-f`) overwrites existing files. The plural form is auto-derived: `generate.module product` and `generate.module products` produce the same `src/app/products/` folder.
|
|
@@ -1554,9 +1554,9 @@ Inside the same module, plain relative imports (`./`, `../`).
|
|
|
1554
1554
|
### Full CRUD bootstrap
|
|
1555
1555
|
|
|
1556
1556
|
```bash
|
|
1557
|
-
|
|
1557
|
+
npx warlock generate.module products
|
|
1558
1558
|
# edit schemas + model fields, then
|
|
1559
|
-
|
|
1559
|
+
npx warlock migrate
|
|
1560
1560
|
```
|
|
1561
1561
|
|
|
1562
1562
|
The CRUD scaffold's `routes.ts` already chains the five controllers behind `guarded(...)`:
|
|
@@ -1584,11 +1584,11 @@ guarded(() => {
|
|
|
1584
1584
|
### Skeleton module, add pieces piecemeal
|
|
1585
1585
|
|
|
1586
1586
|
```bash
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1587
|
+
npx warlock generate.module orders --minimal
|
|
1588
|
+
npx warlock generate.model orders/order --with-resource
|
|
1589
|
+
npx warlock generate.repository orders/order
|
|
1590
|
+
npx warlock generate.controller orders/place-order --with-validation
|
|
1591
|
+
npx warlock generate.controller orders/list-orders
|
|
1592
1592
|
```
|
|
1593
1593
|
|
|
1594
1594
|
Then wire URLs by editing `src/app/orders/routes.ts` and the schema rules in `src/app/orders/schema/`.
|
|
@@ -1609,7 +1609,7 @@ await warmupProductCache();
|
|
|
1609
1609
|
- **There's no standalone `generate.validation` command.** Validation is no longer scaffolded on its own — each controller carries its own schema (imported from `schema/` and bound via `controller.validation`). Generate the controller with `--with-validation` to get the paired schema file, or hand-write the `schema/*.schema.ts`.
|
|
1610
1610
|
- **No `requests/` folder.** Controllers import the schema's exported type + value directly from `schema/*.schema.ts`; there is no `*.request.ts` alias.
|
|
1611
1611
|
- **Subfolder is `seeds/` (plural), not `seed/`.** The seed file is `<module>.seed.ts`.
|
|
1612
|
-
- **`generate.module` does not run the migration.** It only creates the migration file. Run `
|
|
1612
|
+
- **`generate.module` does not run the migration.** It only creates the migration file. Run `npx warlock migrate` separately to apply it.
|
|
1613
1613
|
- **`models/<entity>/` is its own folder, not a flat file.** The generator puts `product.model.ts` inside `models/product/` so migrations can sit beside the model in `models/product/migrations/`.
|
|
1614
1614
|
- **Don't import `routes.ts`, `main.ts`, or anything in `events/`.** They're auto-loaded; double-loading errors out at boot.
|
|
1615
1615
|
- **`utils/locales.ts` is mandatory for translation keys.** Skip it and `t("products.notFound")` silently falls back to the key itself.
|
|
@@ -2292,7 +2292,7 @@ The "same error for missing user vs wrong password" pattern is deliberate — it
|
|
|
2292
2292
|
`hashPassword` / `verifyPassword` need `bcryptjs`. Install it directly:
|
|
2293
2293
|
|
|
2294
2294
|
```bash
|
|
2295
|
-
|
|
2295
|
+
npm install bcryptjs
|
|
2296
2296
|
```
|
|
2297
2297
|
|
|
2298
2298
|
If you skip the install, the first call throws with the framework's install hint:
|
|
@@ -2301,14 +2301,14 @@ If you skip the install, the first call throws with the framework's install hint
|
|
|
2301
2301
|
Password encryption requires the bcryptjs package.
|
|
2302
2302
|
Install it with:
|
|
2303
2303
|
|
|
2304
|
-
|
|
2304
|
+
npm install bcryptjs
|
|
2305
2305
|
|
|
2306
2306
|
Or with your preferred package manager:
|
|
2307
2307
|
|
|
2308
|
-
|
|
2308
|
+
npm install bcryptjs
|
|
2309
2309
|
```
|
|
2310
2310
|
|
|
2311
|
-
There is no `warlock add` feature for password hashing — `bcryptjs` is a plain dependency, so install it directly with `
|
|
2311
|
+
There is no `warlock add` feature for password hashing — `bcryptjs` is a plain dependency, so install it directly with `npm install bcryptjs`.
|
|
2312
2312
|
|
|
2313
2313
|
## Gotchas
|
|
2314
2314
|
|
|
@@ -3288,13 +3288,13 @@ Three commands move the app through its lifecycle: `dev` while you're editing, `
|
|
|
3288
3288
|
|
|
3289
3289
|
```bash
|
|
3290
3290
|
# Local development
|
|
3291
|
-
|
|
3291
|
+
npx warlock dev
|
|
3292
3292
|
|
|
3293
3293
|
# Production build
|
|
3294
|
-
|
|
3294
|
+
npx warlock build
|
|
3295
3295
|
|
|
3296
3296
|
# Run the built bundle
|
|
3297
|
-
|
|
3297
|
+
npx warlock start
|
|
3298
3298
|
```
|
|
3299
3299
|
|
|
3300
3300
|
`dev` and `start` are **persistent** (long-running, no auto-exit). `build` is one-shot — it exits when the bundle is written.
|
|
@@ -3511,9 +3511,9 @@ The three cases that reach it are: never built; a build that failed before promo
|
|
|
3511
3511
|
### Behavior
|
|
3512
3512
|
|
|
3513
3513
|
```bash
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3514
|
+
npx warlock start # → spawns node --enable-source-maps dist/app.js
|
|
3515
|
+
npx warlock start --inspect # → spawns node --enable-source-maps --inspect dist/app.js
|
|
3516
|
+
npx warlock start --max-old-space-size=4096 # → spawns node --enable-source-maps --max-old-space-size=4096 dist/app.js
|
|
3517
3517
|
```
|
|
3518
3518
|
|
|
3519
3519
|
Everything you pass after `start` is forwarded to the spawned Node process. Use this to attach a debugger (`--inspect`), tune memory (`--max-old-space-size`), or pass any other Node flag without editing the command.
|
|
@@ -3565,7 +3565,7 @@ The started banner prints **only** when the running application reports a comple
|
|
|
3565
3565
|
|
|
3566
3566
|
```bash
|
|
3567
3567
|
# a CI gate can be this blunt, and it is now correct
|
|
3568
|
-
|
|
3568
|
+
npx warlock start | grep -q "production server started"
|
|
3569
3569
|
```
|
|
3570
3570
|
|
|
3571
3571
|
### Reading a failed start (5.2)
|
|
@@ -3648,17 +3648,17 @@ If you need conditional behavior, branch on `Application.environment` (the ortho
|
|
|
3648
3648
|
}
|
|
3649
3649
|
```
|
|
3650
3650
|
|
|
3651
|
-
Now `
|
|
3651
|
+
Now `npm run dev` / `npm run build` / `npm run start`. Standard Node hosting providers (Render, Fly, Railway, Heroku) recognize this layout.
|
|
3652
3652
|
|
|
3653
3653
|
### Production Dockerfile
|
|
3654
3654
|
|
|
3655
3655
|
```dockerfile
|
|
3656
3656
|
FROM node:20-alpine AS build
|
|
3657
3657
|
WORKDIR /app
|
|
3658
|
-
COPY package.json
|
|
3659
|
-
RUN
|
|
3658
|
+
COPY package.json package-lock.json ./
|
|
3659
|
+
RUN npm ci
|
|
3660
3660
|
COPY . .
|
|
3661
|
-
RUN
|
|
3661
|
+
RUN npx warlock build
|
|
3662
3662
|
|
|
3663
3663
|
FROM node:20-alpine
|
|
3664
3664
|
WORKDIR /app
|
|
@@ -3667,7 +3667,7 @@ COPY --from=build /app/node_modules ./node_modules
|
|
|
3667
3667
|
COPY --from=build /app/package.json ./
|
|
3668
3668
|
COPY --from=build /app/warlock.config.ts ./
|
|
3669
3669
|
ENV NODE_ENV=production
|
|
3670
|
-
CMD ["
|
|
3670
|
+
CMD ["npx", "warlock", "start"]
|
|
3671
3671
|
```
|
|
3672
3672
|
|
|
3673
3673
|
Two-stage build trims `devDependencies` out of the runtime image. Keep `warlock.config.ts` in the runtime stage — `start` reads it to resolve the bundle path.
|
|
@@ -3702,7 +3702,7 @@ That is deliberate: `build` and `start` do **not** force `production`. Forcing i
|
|
|
3702
3702
|
### Skip type-gen on machines without write access
|
|
3703
3703
|
|
|
3704
3704
|
```bash
|
|
3705
|
-
|
|
3705
|
+
npx warlock dev --skip-typings
|
|
3706
3706
|
```
|
|
3707
3707
|
|
|
3708
3708
|
Or persist it:
|
|
@@ -3720,20 +3720,20 @@ Useful in a containerized dev environment where `.warlock/typings.d.ts` is read-
|
|
|
3720
3720
|
### Memory-tune the production process
|
|
3721
3721
|
|
|
3722
3722
|
```bash
|
|
3723
|
-
|
|
3723
|
+
npx warlock start --max-old-space-size=4096
|
|
3724
3724
|
```
|
|
3725
3725
|
|
|
3726
3726
|
Or via `NODE_OPTIONS` in the deployment env if you don't want to change the start invocation:
|
|
3727
3727
|
|
|
3728
3728
|
```bash
|
|
3729
|
-
NODE_OPTIONS=--max-old-space-size=4096
|
|
3729
|
+
NODE_OPTIONS=--max-old-space-size=4096 npx warlock start
|
|
3730
3730
|
```
|
|
3731
3731
|
|
|
3732
3732
|
## Gotchas
|
|
3733
3733
|
|
|
3734
3734
|
- **`warlock dev` is persistent — `Ctrl+C` to stop.** The framework's `persistent: true` flag keeps the process alive after `action` returns. Same for `start`.
|
|
3735
3735
|
- **`--fresh` only deletes the manifest, not the transpile cache.** If you're chasing a stale-compile bug, `rm -rf .warlock/` clears everything. The manifest restoring is what `--fresh` solves.
|
|
3736
|
-
- **`warlock build` does NOT run migrations.** Production bundles ship the migration files but don't apply them. Run `
|
|
3736
|
+
- **`warlock build` does NOT run migrations.** Production bundles ship the migration files but don't apply them. Run `npx warlock migrate` against the production DB separately.
|
|
3737
3737
|
- **`warlock start` requires a build it can vouch for.** Since 5.2 it refuses any `outdir` without the `.warlock-build.json` success marker — a hand-assembled `dist/`, or one left behind by a build that failed, is rejected by that reason instead of being spawned and crashing halfway through boot. Run `warlock build` first.
|
|
3738
3738
|
- **Do not add `.warlock-build.json` to `.gitignore`-driven artifact pruning.** Stripping it from a `dist/` you ship makes `warlock start` refuse the artifact on the target host. Copy `outdir` whole.
|
|
3739
3739
|
- **`outdir` is the directory, `outFile` is the filename within it.** A common mistake is putting the full path in one and leaving the other default — you end up with `<full-path>/app.js` or `dist/<full-path>`. They concatenate.
|
|
@@ -3840,7 +3840,7 @@ const config: MailConfigurations = {
|
|
|
3840
3840
|
};
|
|
3841
3841
|
```
|
|
3842
3842
|
|
|
3843
|
-
Requires `@aws-sdk/client-sesv2` installed (`
|
|
3843
|
+
Requires `@aws-sdk/client-sesv2` installed (`npm install @aws-sdk/client-sesv2`).
|
|
3844
3844
|
|
|
3845
3845
|
## Mail modes
|
|
3846
3846
|
|
|
@@ -4116,7 +4116,7 @@ await Mail.to(user.email)
|
|
|
4116
4116
|
|
|
4117
4117
|
- **`.send()` validates** — `to`, `subject`, and at least one of `text`/`html`/`component` are required. Missing any throws synchronously.
|
|
4118
4118
|
- **`@react-email/render` is optional.** Without it you get the basic fallback (inline styles, no MSO conditionals). Install it for production-quality HTML.
|
|
4119
|
-
- **`nodemailer` is loaded lazily** at import time. If you see `nodemailer is not installed` errors, run `warlock add mail` (or `
|
|
4119
|
+
- **`nodemailer` is loaded lazily** at import time. If you see `nodemailer is not installed` errors, run `warlock add mail` (or `npm install nodemailer`).
|
|
4120
4120
|
- **`secure: true` requires port 465.** For port 587 use `secure: false` and `tls: true` (STARTTLS).
|
|
4121
4121
|
- **Test mode is process-global.** Set it in `beforeAll`/`beforeEach`; reset with `setMailMode("production")` (or rely on test runner isolation).
|
|
4122
4122
|
- **Per-mail handlers don't replace global ones** — both fire. Avoid double-counting metrics.
|
|
@@ -6894,7 +6894,7 @@ What it does at save time:
|
|
|
6894
6894
|
| Existing row, password unchanged | Pass through (no re-hashing — stored hash preserved). |
|
|
6895
6895
|
| Empty / undefined value | Pass through untouched. |
|
|
6896
6896
|
|
|
6897
|
-
Calls `authService.hashPassword(String(value))` under the hood — same bcryptjs path as the standalone `hashPassword()` helper. See [`hash-password/SKILL.md`](../hash-password/SKILL.md) for full bcrypt setup (salt rounds, `
|
|
6897
|
+
Calls `authService.hashPassword(String(value))` under the hood — same bcryptjs path as the standalone `hashPassword()` helper. See [`hash-password/SKILL.md`](../hash-password/SKILL.md) for full bcrypt setup (salt rounds, `npm install bcryptjs`).
|
|
6898
6898
|
|
|
6899
6899
|
### Why declarative wins
|
|
6900
6900
|
|
|
@@ -7048,7 +7048,7 @@ Rule of thumb: transformers are for **pure, deterministic** transforms of the ro
|
|
|
7048
7048
|
|
|
7049
7049
|
## See also
|
|
7050
7050
|
|
|
7051
|
-
- [`hash-password/SKILL.md`](../hash-password/SKILL.md) — the bcrypt setup that `useHashedPassword` calls under the hood; salt rounds, `
|
|
7051
|
+
- [`hash-password/SKILL.md`](../hash-password/SKILL.md) — the bcrypt setup that `useHashedPassword` calls under the hood; salt rounds, `npm install bcryptjs`.
|
|
7052
7052
|
- [`use-repository/SKILL.md`](../use-repository/SKILL.md) — where `create` / `save` calls happen that trigger the transformers.
|
|
7053
7053
|
- [`define-resource/SKILL.md`](../define-resource/SKILL.md) — filtering transformed fields (`password`) out of API responses.
|
|
7054
7054
|
- [`warlock-conventions/SKILL.md`](../warlock-conventions/SKILL.md) — schema files live in `src/app/<module>/models/<entity>/<entity>.model.ts`.
|
|
@@ -7111,7 +7111,7 @@ Five lines do the heavy lifting:
|
|
|
7111
7111
|
4. **`defaultOptions`** — applied to every call (`orderBy`, default `limit`, etc.).
|
|
7112
7112
|
5. **`new FaqsRepository()`** singleton — import this everywhere; never instantiate again.
|
|
7113
7113
|
|
|
7114
|
-
The class is intentionally private — only the singleton escapes the module. Scaffold with `
|
|
7114
|
+
The class is intentionally private — only the singleton escapes the module. Scaffold with `npx warlock generate.repository <module>/<entity>`.
|
|
7115
7115
|
|
|
7116
7116
|
## The `filterBy` rules
|
|
7117
7117
|
|
|
@@ -7710,7 +7710,7 @@ Two pieces, always:
|
|
|
7710
7710
|
|
|
7711
7711
|
No separate `*.request.ts` alias file. `RequestHandler<Request<TSchema>>` types `request.validated()` directly off the schema's inferred type.
|
|
7712
7712
|
|
|
7713
|
-
Scaffold with `
|
|
7713
|
+
Scaffold with `npx warlock generate.controller <module>/<action> --with-validation`. If the scaffolder emits a `requests/<action>.request.ts` file, delete it — the inline pattern is the convention.
|
|
7714
7714
|
|
|
7715
7715
|
## The `v.*` factory surface
|
|
7716
7716
|
|
|
@@ -8097,7 +8097,7 @@ Cascade uses `@RegisterModel()` for the model registry and `@BelongsTo` / `@HasM
|
|
|
8097
8097
|
|
|
8098
8098
|
---
|
|
8099
8099
|
name: warlock-doctor
|
|
8100
|
-
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 `
|
|
8100
|
+
description: 'Run `warlock doctor` — a read-only diagnostics command that checks routes / config / connectors / optional-peers / health endpoints / release hygiene and prints a pass/warn/fail report, exiting non-zero on any failure. Add your own probe with the `DoctorCheck` contract and `runChecks` / `formatReportLines`. Triggers: `warlock doctor`, `doctorCommand`, `DoctorCheck`, `CheckResult`, `CheckStatus`, `DoctorReport`, `runChecks`, `formatReportLines`, `printReport`, `defaultDoctorChecks`; "diagnose my app", "preflight / preflight check", "is the app healthy", "why are there 0 routes", "pre-release sanity check", "CI smoke check"; run as `npx warlock doctor`. Skip: the live `/health` + `/ready` HTTP probes — `@warlock.js/core/health-checks/SKILL.md`; authoring a general CLI command — `@warlock.js/core/write-cli-command/SKILL.md`; releasing the package — `releasing-warlock-monorepo`; competing tools `npm doctor`, `nest info`, hand-rolled preflight scripts.'
|
|
8101
8101
|
---
|
|
8102
8102
|
|
|
8103
8103
|
# Warlock — `warlock doctor`
|
|
@@ -8105,7 +8105,7 @@ description: 'Run `warlock doctor` — a read-only diagnostics command that chec
|
|
|
8105
8105
|
`warlock doctor` is a read-only preflight. It boots the app far enough to introspect it — loads every config file and bootstrap code so routes and connectors register — but **starts no connectors**, so it never opens a database, cache, or socket connection. It then runs a set of checks and prints a grouped pass / warn / fail report.
|
|
8106
8106
|
|
|
8107
8107
|
```bash
|
|
8108
|
-
|
|
8108
|
+
npx warlock doctor
|
|
8109
8109
|
```
|
|
8110
8110
|
|
|
8111
8111
|
```
|
|
@@ -8208,7 +8208,7 @@ if (report.hasFailures) process.exit(report.exitCode);
|
|
|
8208
8208
|
### CI / pre-release gate
|
|
8209
8209
|
|
|
8210
8210
|
```bash
|
|
8211
|
-
|
|
8211
|
+
npx warlock doctor || exit 1 # non-zero exit fails the job
|
|
8212
8212
|
```
|
|
8213
8213
|
|
|
8214
8214
|
A red `release-hygiene` line catches the classic "bumped `package.json` but forgot the CHANGELOG heading" mistake before a publish.
|
|
@@ -8236,7 +8236,7 @@ A `⚠ routes: 0 routes registered` line is the tell that a route module threw o
|
|
|
8236
8236
|
|
|
8237
8237
|
---
|
|
8238
8238
|
name: warlock-routes
|
|
8239
|
-
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 `
|
|
8239
|
+
description: 'Run `warlock routes` — a read-only command that lists the registered HTTP routes as a verb-colored table (method / path / name / action / middleware-count / source), a sibling of `warlock doctor`. Filter with `--method` / `--path` / `--name`, or emit normalized rows as JSON with `--json`. Also covers `warlock routes:diff`, which compares live page routes against the last `warlock build`''s route snapshot and exits non-zero on drift. Triggers: `warlock routes`, `routesCommand`, `warlock routes:diff`, `routesDiffCommand`, "list my routes", "show all routes", "route table", "what endpoints does my app expose", "dump routes as JSON", "which routes have middleware", "route map for CI", "did my page routes drift from the last build"; run as `npx warlock routes` / `npx warlock routes:diff`. Skip: read-only health/preflight checks — `@warlock.js/core/warlock-doctor/SKILL.md`; defining/naming/grouping routes — `@warlock.js/core/register-route/SKILL.md`; authoring a general CLI command — `@warlock.js/core/write-cli-command/SKILL.md`; competing tools `nest`/`express` route listers, `php artisan route:list`.'
|
|
8240
8240
|
---
|
|
8241
8241
|
|
|
8242
8242
|
# Warlock — `warlock routes`
|
|
@@ -8244,7 +8244,7 @@ description: 'Run `warlock routes` — a read-only command that lists the regist
|
|
|
8244
8244
|
`warlock routes` lists every registered HTTP route as a table. It's the read-only sibling of [`warlock doctor`](../warlock-doctor/SKILL.md): it boots the app far enough to register route modules — but **starts no connectors**, so it never opens a database, cache, or socket connection.
|
|
8245
8245
|
|
|
8246
8246
|
```bash
|
|
8247
|
-
|
|
8247
|
+
npx warlock routes
|
|
8248
8248
|
```
|
|
8249
8249
|
|
|
8250
8250
|
```
|
|
@@ -8275,10 +8275,10 @@ The `METHOD` column is verb-colored (GET green, POST blue, PUT/PATCH yellow, DEL
|
|
|
8275
8275
|
Optional, case-insensitive, AND-combined:
|
|
8276
8276
|
|
|
8277
8277
|
```bash
|
|
8278
|
-
|
|
8279
|
-
|
|
8280
|
-
|
|
8281
|
-
|
|
8278
|
+
npx warlock routes --method GET # -m exact HTTP method
|
|
8279
|
+
npx warlock routes --path /users # -p path substring
|
|
8280
|
+
npx warlock routes --name users # -n route-name substring
|
|
8281
|
+
npx warlock routes -m POST -p /users
|
|
8282
8282
|
```
|
|
8283
8283
|
|
|
8284
8284
|
## JSON output
|
|
@@ -8286,7 +8286,7 @@ pnpm warlock routes -m POST -p /users
|
|
|
8286
8286
|
`--json` (`-j`) emits the normalized rows instead of the table — for `jq`, a CI diff, or a generated API map. Filters apply before serialization.
|
|
8287
8287
|
|
|
8288
8288
|
```bash
|
|
8289
|
-
|
|
8289
|
+
npx warlock routes --json
|
|
8290
8290
|
```
|
|
8291
8291
|
|
|
8292
8292
|
```json
|
|
@@ -8300,7 +8300,7 @@ pnpm warlock routes --json
|
|
|
8300
8300
|
### Audit which routes are guarded
|
|
8301
8301
|
|
|
8302
8302
|
```bash
|
|
8303
|
-
|
|
8303
|
+
npx warlock routes --json | jq '[.[] | select(.middleware == 0)]'
|
|
8304
8304
|
```
|
|
8305
8305
|
|
|
8306
8306
|
Surfaces public routes (no middleware) — a quick check that auth-protected paths actually carry a guard.
|
|
@@ -8308,7 +8308,7 @@ Surfaces public routes (no middleware) — a quick check that auth-protected pat
|
|
|
8308
8308
|
### Confirm a route registered
|
|
8309
8309
|
|
|
8310
8310
|
```bash
|
|
8311
|
-
|
|
8311
|
+
npx warlock routes --name users.create
|
|
8312
8312
|
```
|
|
8313
8313
|
|
|
8314
8314
|
An empty result means the route isn't registered — re-run `warlock dev` and read the boot error (the route-module loader is fail-loud, so a throwing route file aborts boot rather than being silently dropped).
|
|
@@ -8318,7 +8318,7 @@ An empty result means the route isn't registered — re-run `warlock dev` and re
|
|
|
8318
8318
|
Compares the **live dev-server page routes** (`router.list().filter(r => r.isPage)`) against a **snapshot written by the last successful `warlock build`** (`page-routes.manifest.json` in `resolveBuildConfig().outdir`, e.g. `dist/page-routes.manifest.json`). Boots the same diagnostic way as `warlock routes` — route modules registered, no connectors started — then diffs.
|
|
8319
8319
|
|
|
8320
8320
|
```bash
|
|
8321
|
-
|
|
8321
|
+
npx warlock routes:diff
|
|
8322
8322
|
```
|
|
8323
8323
|
|
|
8324
8324
|
```
|
|
@@ -8696,7 +8696,7 @@ export default command({
|
|
|
8696
8696
|
});
|
|
8697
8697
|
```
|
|
8698
8698
|
|
|
8699
|
-
Run it: `
|
|
8699
|
+
Run it: `npx warlock users.promote --email=hasan@example.com` (or `npx warlock up -e hasan@example.com`).
|
|
8700
8700
|
|
|
8701
8701
|
## `CLICommandOptions` — the factory input
|
|
8702
8702
|
|
|
@@ -9229,12 +9229,12 @@ export default seeder({
|
|
|
9229
9229
|
Run them:
|
|
9230
9230
|
|
|
9231
9231
|
```bash
|
|
9232
|
-
|
|
9233
|
-
|
|
9234
|
-
|
|
9235
|
-
|
|
9236
|
-
|
|
9237
|
-
|
|
9232
|
+
npx warlock seed # discover + run all
|
|
9233
|
+
npx warlock seed --list # show registry, don't run
|
|
9234
|
+
npx warlock seed --path=src/app/roles/seeds/default-roles.seed.ts # one file
|
|
9235
|
+
npx warlock seed --fresh # truncate every table first, then run all
|
|
9236
|
+
npx warlock seed --drop # undo every tracked record, reset the log
|
|
9237
|
+
npx warlock seed --drop=default-roles # undo just one seeder's records
|
|
9238
9238
|
```
|
|
9239
9239
|
|
|
9240
9240
|
`--fresh` truncates **every** table in the DB (`datasource.driver.truncateTable(table, { cascade: true })`), including the `seeds` tracking table. After `--fresh`, `once: true` seeds will run again.
|
|
@@ -9372,8 +9372,8 @@ Every record you `track()` is written to a `seed_records` table (created on firs
|
|
|
9372
9372
|
`warlock seed --drop` reads those refs and undoes the seed:
|
|
9373
9373
|
|
|
9374
9374
|
```bash
|
|
9375
|
-
|
|
9376
|
-
|
|
9375
|
+
npx warlock seed --drop # undo every tracked record across all seeders
|
|
9376
|
+
npx warlock seed --drop=default-roles # undo just one seeder's records
|
|
9377
9377
|
```
|
|
9378
9378
|
|
|
9379
9379
|
What it does, inside a single transaction:
|
package/llms.txt
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
- [build-url](@warlock.js/core/build-url/SKILL.md): HTTP URL helpers — `url`, `publicUrl`, `assetsUrl`, `uploadsUrl`, anchored at `app.baseUrl`. Use to render `src` / `href` / API URLs in resources and responses. `setBaseUrl` is wired by the HTTP connector from `config.get("app.baseUrl")`. Triggers: `url`, `publicUrl`, `assetsUrl`, `uploadsUrl`, `setBaseUrl`, `BASE_URL`; "render an avatar src URL", "absolute download link", "embed asset URL in email", "URL helpers vs path helpers"; typical import `import { url, publicUrl, uploadsUrl } from "@warlock.js/core"`. Skip: filesystem paths — `@warlock.js/core/resolve-path/SKILL.md`; signed CDN URLs — `@warlock.js/core/store-file/SKILL.md`; resource output — `@warlock.js/core/define-resource/SKILL.md`; competing patterns: hand-rolled `${baseUrl}/...` template strings.
|
|
13
13
|
- [configure-app](@warlock.js/core/configure-app/SKILL.md): Configure a Warlock app — the two layers (`warlock.config.ts` for framework-level wiring, `src/config/*.ts` for subsystems), `.env` + `env()`, and the `config()` getter for runtime reads. Triggers: `defineConfig`, `config.get`, `config.key`, `env`, `ConfigRegistry`, `HttpConfigurations`, `AppConfigurations`; "add a new config file", "warlock.config.ts vs src/config", "read env values", "runtime config lookup"; typical import `import { defineConfig, config, env } from "@warlock.js/core"`. Skip: cache driver registration — `@warlock.js/cache/cache-basics/SKILL.md`; mail config — `@warlock.js/core/send-mail/SKILL.md`; storage config — `@warlock.js/core/store-file/SKILL.md`; competing libs `dotenv` direct, `convict`, `node-config`.
|
|
14
14
|
- [create-controller](@warlock.js/core/create-controller/SKILL.md): Author HTTP controllers in @warlock.js/core — RequestHandler signature, validated input via seal schemas, response helpers, attaching metadata. Controllers are thin functions; business logic moves to services or use-cases. Triggers: `RequestHandler`, `Request<TSchema>`, `GuardedRequestHandler`, `request.validated`, `request.input`, `controller.validation`, `response.success`, `response.successCreate`; "write a controller", "attach a schema to a handler", "thin controller pattern", "guarded request type"; typical import `import { type RequestHandler } from "@warlock.js/core"`. Skip: response helper menu — `@warlock.js/core/send-response/SKILL.md`; schema authoring — `@warlock.js/core/validate-input/SKILL.md`; URL wiring — `@warlock.js/core/register-route/SKILL.md`; competing patterns: `express` middleware functions, `@nestjs/common` `@Controller`/`@Get` decorators.
|
|
15
|
-
- [create-module](@warlock.js/core/create-module/SKILL.md): 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 `
|
|
15
|
+
- [create-module](@warlock.js/core/create-module/SKILL.md): Scaffold a new feature module under `src/app/<name>/` via `warlock generate.module` and the follow-up generators for controllers, models, repositories, resources, and validation schemas. Triggers: `warlock generate.module`, `generate.controller`, `generate.service`, `generate.model`, `generate.repository`, `generate.resource`, `generate.migration`, `--minimal`, `gen.m`; "scaffold a new module", "create CRUD bootstrap", "add a controller to a module", "generate a model"; typical CLI `npx warlock generate.module <name>`. Skip: framework-wide layout rules — `@warlock.js/core/warlock-conventions/SKILL.md`; routes file shape — `@warlock.js/core/register-route/SKILL.md`; controller shape — `@warlock.js/core/create-controller/SKILL.md`; competing tooling: `@nestjs/cli`, `hygen`, hand-rolled folder layouts.
|
|
16
16
|
- [define-resource](@warlock.js/core/define-resource/SKILL.md): Map model fields to wire-shape via `defineResource()` or `Resource` subclasses. Output-only — never put business logic, hydration, or reconciliation in a resource. Triggers: `defineResource`, `Resource`, `RegisterResource`, `toJSON`, `"self"`, `"localized"`, `"uploadsUrl"`; "shape an API response", "nest related resources", "rename a field on output", "self-referential tree resource"; typical import `import { defineResource } from "@warlock.js/core"`. Skip: localized columns — `@warlock.js/core/use-localization/SKILL.md`; URL casting — `@warlock.js/core/build-url/SKILL.md`; controller side — `@warlock.js/core/create-controller/SKILL.md`; competing libs `@nestjs/swagger` `@ApiProperty`, `class-transformer`, hand-rolled DTO mappers.
|
|
17
17
|
- [encrypt-data](@warlock.js/core/encrypt-data/SKILL.md): Reversible AES-256-GCM `encrypt` / `decrypt` for secrets you need to read back; one-way HMAC-SHA256 `hmacHash` for deterministic fingerprints (lookup/dedup of encrypted columns). Keys come from `src/config/encryption.ts`. Triggers: `encrypt`, `decrypt`, `hmacHash`, `EncryptionConfigurations`, `APP_ENCRYPTION_KEY`, `APP_HMAC_KEY`; "store an API key reversibly", "fingerprint an encrypted column for lookup", "AES-256-GCM secret", "HMAC-SHA256 dedup key"; typical import `import { encrypt, decrypt, hmacHash } from "@warlock.js/core"`. Skip: password hashing — `@warlock.js/core/hash-password/SKILL.md`; config wiring — `@warlock.js/core/configure-app/SKILL.md`; competing libs Node `crypto` direct, `crypto-js`, `libsodium-wrappers`.
|
|
18
18
|
- [hash-password](@warlock.js/core/hash-password/SKILL.md): One-way bcrypt password hashing — `hashPassword` / `verifyPassword`, plus the declarative `useHashedPassword()` schema transformer that auto-hashes a model's password field on save. Salt rounds come from `src/config/encryption.ts`. Triggers: `hashPassword`, `verifyPassword`, `useHashedPassword`, `password.salt`, `bcryptjs`; "hash a user password", "verify login credentials", "auto-hash on save", "rotate a password"; typical import `import { hashPassword, verifyPassword } from "@warlock.js/core"`. Skip: reversible secrets — `@warlock.js/core/encrypt-data/SKILL.md`; the other transformers — `@warlock.js/core/use-model-transformers/SKILL.md`; config wiring — `@warlock.js/core/configure-app/SKILL.md`; competing libs `bcrypt` native, `argon2`, `scrypt`.
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
- [use-request-locals](@warlock.js/core/use-request-locals/SKILL.md): Carry typed, server-only data through one HTTP request with `request.locals`, usually written by middleware and read by downstream middleware or controllers. Augment `RequestLocals` in the module that owns each key; v5 no longer permits arbitrary `request.foo` properties. Triggers: `request.locals`, `RequestLocals`, `request.post`, `request.organization`, `Property does not exist on type Request`, `Request index signature`; "attach data to a request", "share middleware data with a controller", "type request locals", "migrate dynamic request properties"; typical type augmentation `declare module "@warlock.js/core" { interface RequestLocals { ... } }`. Skip: computed-on-demand single-flight values and removed `fromRequest` — `@warlock.js/core/request-memo/SKILL.md`; middleware mechanics — `@warlock.js/core/write-middleware/SKILL.md`; authenticated user typing — augment `RequestUser`, not `RequestLocals`; competing patterns: `(request as any).foo`, `request.set()`, module-global mutable state.
|
|
40
40
|
- [validate-input](@warlock.js/core/validate-input/SKILL.md): Author seal schemas, attach them to controllers via `controller.validation = { schema }`, infer types via `Infer<typeof schema>`, and layer DB-aware (`unique`/`exists`) and file validators on top. Triggers: `v.object`, `v.string`, `v.email`, `Infer`, `controller.validation`, `.unique`, `.exists`, `uniqueExceptCurrentId`, `request.validated`; "validate a request body", "attach a schema to a controller", "DB-aware unique rule", "infer schema types"; typical import `import { v, type Infer } from "@warlock.js/seal"`. Skip: schema authoring foundations — `@warlock.js/seal/seal-basics/SKILL.md`; controller wiring — `@warlock.js/core/create-controller/SKILL.md`; file rules deep-dive — `@warlock.js/core/upload-file/SKILL.md`; competing libs `zod`, `joi`, `yup`, `class-validator`.
|
|
41
41
|
- [warlock-conventions](@warlock.js/core/warlock-conventions/SKILL.md): Framework-wide invariants for projects built on @warlock.js/core — module layout, canonical imports, layered flow, file naming, and the non-negotiable rules every other warlock skill assumes. Triggers: `src/app/<module>`, `routes.ts`, `main.ts`, `Request<TSchema>`, `RequestHandler`, `GuardedRequestHandler`, `app/<module>/...`; "where do files go in this project", "canonical Warlock imports", "module layout rules", "controller-service-repository layering"; typical import `import { router, type RequestHandler } from "@warlock.js/core"`. Skip: scaffold a new module — `@warlock.js/core/create-module/SKILL.md`; route shape — `@warlock.js/core/register-route/SKILL.md`; controller shape — `@warlock.js/core/create-controller/SKILL.md`; competing patterns: `express` ad-hoc layouts, `@nestjs/common` decorator-driven structure.
|
|
42
|
-
- [warlock-doctor](@warlock.js/core/warlock-doctor/SKILL.md): 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 `
|
|
43
|
-
- [warlock-routes](@warlock.js/core/warlock-routes/SKILL.md): 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 `
|
|
42
|
+
- [warlock-doctor](@warlock.js/core/warlock-doctor/SKILL.md): Run `warlock doctor` — a read-only diagnostics command that checks routes / config / connectors / optional-peers / health endpoints / release hygiene and prints a pass/warn/fail report, exiting non-zero on any failure. Add your own probe with the `DoctorCheck` contract and `runChecks` / `formatReportLines`. Triggers: `warlock doctor`, `doctorCommand`, `DoctorCheck`, `CheckResult`, `CheckStatus`, `DoctorReport`, `runChecks`, `formatReportLines`, `printReport`, `defaultDoctorChecks`; "diagnose my app", "preflight / preflight check", "is the app healthy", "why are there 0 routes", "pre-release sanity check", "CI smoke check"; run as `npx warlock doctor`. Skip: the live `/health` + `/ready` HTTP probes — `@warlock.js/core/health-checks/SKILL.md`; authoring a general CLI command — `@warlock.js/core/write-cli-command/SKILL.md`; releasing the package — `releasing-warlock-monorepo`; competing tools `npm doctor`, `nest info`, hand-rolled preflight scripts.
|
|
43
|
+
- [warlock-routes](@warlock.js/core/warlock-routes/SKILL.md): Run `warlock routes` — a read-only command that lists the registered HTTP routes as a verb-colored table (method / path / name / action / middleware-count / source), a sibling of `warlock doctor`. Filter with `--method` / `--path` / `--name`, or emit normalized rows as JSON with `--json`. Also covers `warlock routes:diff`, which compares live page routes against the last `warlock build`'s route snapshot and exits non-zero on drift. Triggers: `warlock routes`, `routesCommand`, `warlock routes:diff`, `routesDiffCommand`, "list my routes", "show all routes", "route table", "what endpoints does my app expose", "dump routes as JSON", "which routes have middleware", "route map for CI", "did my page routes drift from the last build"; run as `npx warlock routes` / `npx warlock routes:diff`. Skip: read-only health/preflight checks — `@warlock.js/core/warlock-doctor/SKILL.md`; defining/naming/grouping routes — `@warlock.js/core/register-route/SKILL.md`; authoring a general CLI command — `@warlock.js/core/write-cli-command/SKILL.md`; competing tools `nest`/`express` route listers, `php artisan route:list`.
|
|
44
44
|
- [wire-socket](@warlock.js/core/wire-socket/SKILL.md): Configure Socket.IO via `src/config/socket.ts`, reach the live server through `getSocketServer()` (or `app.socket` post-bootstrap), register `connection` handlers once the late-phase socket connector has booted, emit from controllers/services, use rooms and namespaces. Triggers: `app.socket`, `getSocketServer`, `SocketOptions`, `socket.io` `Server`, `socket.join`, `socket.to`, `io.of`, `io.use`; "add realtime chat", "emit socket events from a service", "use rooms and namespaces", "per-socket JWT auth". Skip: connector lifecycle — `@warlock.js/core/add-connector/SKILL.md`; app context accessors — `@warlock.js/core/use-app-context/SKILL.md`; competing libs `ws`, `socket.io` direct without Warlock connector, `uWebSockets.js`.
|
|
45
45
|
- [write-cli-command](@warlock.js/core/write-cli-command/SKILL.md): 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`, `index.register.ts`; "write a custom warlock command", "one-off maintenance task", "ship a CLI from a package", "framework built-in commands"; typical import `import { command } from "@warlock.js/core"`. Skip: framework dev/build/start — `@warlock.js/core/run-app/SKILL.md`; warlock.config.ts wiring — `@warlock.js/core/configure-app/SKILL.md`; competing libs `commander`, `yargs`, `oclif`.
|
|
46
46
|
- [write-middleware](@warlock.js/core/write-middleware/SKILL.md): Author HTTP middleware for @warlock.js/core — the `({ request, response })` signature, short-circuit by returning a response, enrich the request with extra fields, register per-route, per-group, or app-wide. Triggers: `Middleware`, `MiddlewareResponse`, `router.group`, `guarded`, `request.detectIp`, `authMiddleware`; "write a custom middleware", "short-circuit a request", "enrich the request with extra fields", "per-route vs per-group middleware"; typical import `import type { Middleware } from "@warlock.js/core"`. Skip: built-in middleware catalog — `@warlock.js/core/use-middleware/SKILL.md`; route attachment — `@warlock.js/core/register-route/SKILL.md`; response helpers — `@warlock.js/core/send-response/SKILL.md`; competing patterns: `express` `(req, res, next)` middleware, Fastify `preHandler` hooks.
|
package/package.json
CHANGED
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
"@mongez/slug": "^1.0.7",
|
|
26
26
|
"@mongez/supportive-is": "^2.1.4",
|
|
27
27
|
"@mongez/time-wizard": "^1.0.6",
|
|
28
|
-
"@warlock.js/auth": "5.
|
|
29
|
-
"@warlock.js/cache": "5.
|
|
30
|
-
"@warlock.js/cascade": "5.
|
|
31
|
-
"@warlock.js/context": "5.
|
|
32
|
-
"@warlock.js/logger": "5.
|
|
33
|
-
"@warlock.js/seal": "5.
|
|
34
|
-
"@warlock.js/fs": "5.
|
|
28
|
+
"@warlock.js/auth": "5.6.0",
|
|
29
|
+
"@warlock.js/cache": "5.6.0",
|
|
30
|
+
"@warlock.js/cascade": "5.6.0",
|
|
31
|
+
"@warlock.js/context": "5.6.0",
|
|
32
|
+
"@warlock.js/logger": "5.6.0",
|
|
33
|
+
"@warlock.js/seal": "5.6.0",
|
|
34
|
+
"@warlock.js/fs": "5.6.0",
|
|
35
35
|
"chokidar": "^5.0.0",
|
|
36
36
|
"dayjs": "^1.11.19",
|
|
37
37
|
"es-module-lexer": "^2.0.0",
|
|
@@ -57,10 +57,10 @@
|
|
|
57
57
|
"react": "^19.2.3",
|
|
58
58
|
"react-dom": "^19.2.3",
|
|
59
59
|
"@react-email/render": "^2.0.5",
|
|
60
|
-
"@warlock.js/herald": "5.
|
|
61
|
-
"@warlock.js/ai": "5.
|
|
62
|
-
"@warlock.js/access": "5.
|
|
63
|
-
"@warlock.js/notifications": "5.
|
|
60
|
+
"@warlock.js/herald": "5.6.0",
|
|
61
|
+
"@warlock.js/ai": "5.6.0",
|
|
62
|
+
"@warlock.js/access": "5.6.0",
|
|
63
|
+
"@warlock.js/notifications": "5.6.0"
|
|
64
64
|
},
|
|
65
65
|
"peerDependenciesMeta": {
|
|
66
66
|
"sharp": {
|
|
@@ -123,7 +123,7 @@
|
|
|
123
123
|
],
|
|
124
124
|
"author": "hassanzohdy",
|
|
125
125
|
"license": "MIT",
|
|
126
|
-
"version": "5.
|
|
126
|
+
"version": "5.6.0",
|
|
127
127
|
"type": "module",
|
|
128
128
|
"main": "./esm/index.mjs",
|
|
129
129
|
"module": "./esm/index.mjs",
|
|
@@ -25,7 +25,7 @@ That's the full contract. The `RequestHandler` annotation carries both parameter
|
|
|
25
25
|
- File: `src/app/<module>/controllers/<action>.controller.ts`.
|
|
26
26
|
- Export name matches the action in camelCase + `Controller` suffix: `listProductsController`, `createProductController`, `getProductController`.
|
|
27
27
|
|
|
28
|
-
Scaffold with: `
|
|
28
|
+
Scaffold with: `npx warlock generate.controller <module>/<action>` (add `--with-validation` to get the schema generated alongside).
|
|
29
29
|
|
|
30
30
|
## Reading input
|
|
31
31
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: create-module
|
|
3
|
-
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 `
|
|
3
|
+
description: 'Scaffold a new feature module under `src/app/<name>/` via `warlock generate.module` and the follow-up generators for controllers, models, repositories, resources, and validation schemas. Triggers: `warlock generate.module`, `generate.controller`, `generate.service`, `generate.model`, `generate.repository`, `generate.resource`, `generate.migration`, `--minimal`, `gen.m`; "scaffold a new module", "create CRUD bootstrap", "add a controller to a module", "generate a model"; typical CLI `npx warlock generate.module <name>`. Skip: framework-wide layout rules — `@warlock.js/core/warlock-conventions/SKILL.md`; routes file shape — `@warlock.js/core/register-route/SKILL.md`; controller shape — `@warlock.js/core/create-controller/SKILL.md`; competing tooling: `@nestjs/cli`, `hygen`, hand-rolled folder layouts.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Warlock — create a module
|
|
@@ -10,8 +10,8 @@ A module is a self-contained feature folder under `src/app/<name>/`. The CLI sca
|
|
|
10
10
|
## The shape
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
npx warlock generate.module products # full CRUD bootstrap (default — controllers, model, services, repository, resource, schemas, routes, seed)
|
|
14
|
+
npx warlock generate.module products --minimal # bare bones (routes.ts + main.ts + utils/locales.ts + empty subfolders)
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
Full CRUD is the default — opt down to a bare skeleton with `--minimal` (`-m`) when you want to build the module piece by piece. `--force` (`-f`) overwrites existing files. The plural form is auto-derived: `generate.module product` and `generate.module products` produce the same `src/app/products/` folder.
|
|
@@ -117,9 +117,9 @@ Inside the same module, plain relative imports (`./`, `../`).
|
|
|
117
117
|
### Full CRUD bootstrap
|
|
118
118
|
|
|
119
119
|
```bash
|
|
120
|
-
|
|
120
|
+
npx warlock generate.module products
|
|
121
121
|
# edit schemas + model fields, then
|
|
122
|
-
|
|
122
|
+
npx warlock migrate
|
|
123
123
|
```
|
|
124
124
|
|
|
125
125
|
The CRUD scaffold's `routes.ts` already chains the five controllers behind `guarded(...)`:
|
|
@@ -147,11 +147,11 @@ guarded(() => {
|
|
|
147
147
|
### Skeleton module, add pieces piecemeal
|
|
148
148
|
|
|
149
149
|
```bash
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
150
|
+
npx warlock generate.module orders --minimal
|
|
151
|
+
npx warlock generate.model orders/order --with-resource
|
|
152
|
+
npx warlock generate.repository orders/order
|
|
153
|
+
npx warlock generate.controller orders/place-order --with-validation
|
|
154
|
+
npx warlock generate.controller orders/list-orders
|
|
155
155
|
```
|
|
156
156
|
|
|
157
157
|
Then wire URLs by editing `src/app/orders/routes.ts` and the schema rules in `src/app/orders/schema/`.
|
|
@@ -172,7 +172,7 @@ await warmupProductCache();
|
|
|
172
172
|
- **There's no standalone `generate.validation` command.** Validation is no longer scaffolded on its own — each controller carries its own schema (imported from `schema/` and bound via `controller.validation`). Generate the controller with `--with-validation` to get the paired schema file, or hand-write the `schema/*.schema.ts`.
|
|
173
173
|
- **No `requests/` folder.** Controllers import the schema's exported type + value directly from `schema/*.schema.ts`; there is no `*.request.ts` alias.
|
|
174
174
|
- **Subfolder is `seeds/` (plural), not `seed/`.** The seed file is `<module>.seed.ts`.
|
|
175
|
-
- **`generate.module` does not run the migration.** It only creates the migration file. Run `
|
|
175
|
+
- **`generate.module` does not run the migration.** It only creates the migration file. Run `npx warlock migrate` separately to apply it.
|
|
176
176
|
- **`models/<entity>/` is its own folder, not a flat file.** The generator puts `product.model.ts` inside `models/product/` so migrations can sit beside the model in `models/product/migrations/`.
|
|
177
177
|
- **Don't import `routes.ts`, `main.ts`, or anything in `events/`.** They're auto-loaded; double-loading errors out at boot.
|
|
178
178
|
- **`utils/locales.ts` is mandatory for translation keys.** Skip it and `t("products.notFound")` silently falls back to the key itself.
|
|
@@ -148,7 +148,7 @@ The "same error for missing user vs wrong password" pattern is deliberate — it
|
|
|
148
148
|
`hashPassword` / `verifyPassword` need `bcryptjs`. Install it directly:
|
|
149
149
|
|
|
150
150
|
```bash
|
|
151
|
-
|
|
151
|
+
npm install bcryptjs
|
|
152
152
|
```
|
|
153
153
|
|
|
154
154
|
If you skip the install, the first call throws with the framework's install hint:
|
|
@@ -157,14 +157,14 @@ If you skip the install, the first call throws with the framework's install hint
|
|
|
157
157
|
Password encryption requires the bcryptjs package.
|
|
158
158
|
Install it with:
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
npm install bcryptjs
|
|
161
161
|
|
|
162
162
|
Or with your preferred package manager:
|
|
163
163
|
|
|
164
|
-
|
|
164
|
+
npm install bcryptjs
|
|
165
165
|
```
|
|
166
166
|
|
|
167
|
-
There is no `warlock add` feature for password hashing — `bcryptjs` is a plain dependency, so install it directly with `
|
|
167
|
+
There is no `warlock add` feature for password hashing — `bcryptjs` is a plain dependency, so install it directly with `npm install bcryptjs`.
|
|
168
168
|
|
|
169
169
|
## Gotchas
|
|
170
170
|
|