@warlock.js/core 5.12.0 → 5.14.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 +86 -54
- package/esm/cli/commands/build.command.mjs.map +1 -1
- package/esm/cli/commands/dev-server.command.mjs +2 -0
- package/esm/cli/commands/dev-server.command.mjs.map +1 -1
- package/esm/database/utils.d.mts +5 -1
- package/esm/database/utils.d.mts.map +1 -1
- package/esm/database/utils.mjs +7 -3
- package/esm/database/utils.mjs.map +1 -1
- package/esm/dev-server/file-event-handler.mjs +23 -5
- package/esm/dev-server/file-event-handler.mjs.map +1 -1
- package/esm/dev-server/files-watcher.mjs +6 -3
- package/esm/dev-server/files-watcher.mjs.map +1 -1
- package/esm/dev-server/translation-type-generator.mjs +28 -0
- package/esm/dev-server/translation-type-generator.mjs.map +1 -0
- package/esm/dev-server/tsconfig-manager.mjs +1 -0
- package/esm/dev-server/tsconfig-manager.mjs.map +1 -1
- package/esm/dev-server/type-generator.mjs +41 -5
- package/esm/dev-server/type-generator.mjs.map +1 -1
- package/esm/encryption/index.mjs +1 -1
- package/esm/errors/esbuild-binary-missing-error.mjs +20 -0
- package/esm/errors/esbuild-binary-missing-error.mjs.map +1 -0
- package/esm/generations/features/auth-google.feature.mjs +18 -0
- package/esm/generations/features/auth-google.feature.mjs.map +1 -0
- package/esm/generations/features/auth-passkeys.feature.mjs +19 -0
- package/esm/generations/features/auth-passkeys.feature.mjs.map +1 -0
- package/esm/generations/features/bull-board.feature.mjs +65 -0
- package/esm/generations/features/bull-board.feature.mjs.map +1 -0
- package/esm/generations/features/index.mjs +8 -0
- package/esm/generations/features/index.mjs.map +1 -1
- package/esm/generations/features/queue.feature.mjs +70 -0
- package/esm/generations/features/queue.feature.mjs.map +1 -0
- package/esm/generations/features/shared/insert-connector-entry.mjs +68 -0
- package/esm/generations/features/shared/insert-connector-entry.mjs.map +1 -0
- package/esm/generations/features/shared/insert-queue-dashboard-block.mjs +55 -0
- package/esm/generations/features/shared/insert-queue-dashboard-block.mjs.map +1 -0
- package/esm/generations/features/web.feature.mjs +4 -1
- package/esm/generations/features/web.feature.mjs.map +1 -1
- package/esm/generations/stubs.mjs +4 -4
- package/esm/generations/stubs.mjs.map +1 -1
- package/esm/http/middleware/cache-response-middleware.d.mts +12 -0
- package/esm/http/middleware/cache-response-middleware.d.mts.map +1 -1
- package/esm/http/middleware/cache-response-middleware.mjs +15 -3
- package/esm/http/middleware/cache-response-middleware.mjs.map +1 -1
- package/esm/index.mjs +1 -1
- package/esm/production/esbuild-preflight.mjs +23 -13
- package/esm/production/esbuild-preflight.mjs.map +1 -1
- package/llms-full.txt +56 -24
- package/llms.txt +2 -2
- package/package.json +11 -12
- package/skills/run-app/SKILL.md +6 -2
- package/skills/use-localization/SKILL.md +24 -21
- package/skills/use-middleware/SKILL.md +24 -0
- package/skills/write-cli-command/SKILL.md +2 -1
package/llms.txt
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
- [request-tracing](@warlock.js/core/request-tracing/SKILL.md): Vendor-neutral request tracing hooks (`http.tracing`) — observe request start/end and named phase spans (`route.match`, `middleware`, `validation`, `handler`, `response.write`) without adopting an OTel/vendor dependency in `core`. Covers the `TracingHooks` shape, trace id derivation from an inbound W3C `traceparent` vs `request.id`, that a throwing hook is caught and reported once (never breaks the request), and zero overhead when disabled. Triggers: `http.tracing`, `TracingHooks`, `onRequestStart`, `onRequestEnd`, `onPhase`, `traceparent`, `traceId`, `dispatchPhase`, "instrument requests", "trace a request", "slow phase logging", "APM / OTel bridge for Warlock". Skip: request-id header echo/inheritance (`X-Request-Id`) — `@warlock.js/core/use-middleware/SKILL.md`; app-level structured logging — `@warlock.js/logger/logger-basics/SKILL.md`; competing libs `@opentelemetry/api` direct instrumentation, `express-request-id`, hand-rolled `X-Trace-Id` middleware.
|
|
25
25
|
- [resolve-path](@warlock.js/core/resolve-path/SKILL.md): Path helpers anchored at `process.cwd()` — `rootPath`, `srcPath`, `appPath`, `configPath`, `publicPath`, `storagePath`, `uploadsPath`, `cachePath`, `logsPath`, `tempPath`, `warlockPath`, `sanitizePath`. Optional `uploads.root` config overrides the uploads anchor. Triggers: `appPath`, `configPath`, `uploadsPath`, `storagePath`, `publicPath`, `cachePath`, `logsPath`, `tempPath`, `sanitizePath`, `paths`; "resolve a path inside src/app", "absolute upload destination", "sanitize a user filename", "ship uploads to a mounted volume"; typical import `import { appPath, uploadsPath } from "@warlock.js/core"`. Skip: HTTP URL helpers — `@warlock.js/core/build-url/SKILL.md`; app metadata — `@warlock.js/core/use-app-context/SKILL.md`; storage abstraction — `@warlock.js/core/store-file/SKILL.md`; competing patterns: `path.join(process.cwd(), ...)`, hand-rolled directory constants.
|
|
26
26
|
- [retry-operation](@warlock.js/core/retry-operation/SKILL.md): Wrap a flaky operation with `retry(fn, options)` — now provided by `@mongez/reinforcements` (not `@warlock.js/core`). `attempts` total tries, `delay` + `backoff` (linear/exponential/fn), `maxDelay`, `jitter`, `shouldRetry` to bail on permanent errors, `signal` to cancel, plus `retryable()` to pre-bind options. Triggers: `retry`, `retryable`, `RetryOptions`, `attempts`, `backoff`, `jitter`, `maxDelay`, `shouldRetry`, `signal`; "retry a flaky API call", "handle transient errors", "exponential backoff with jitter", "wrap an external request"; typical import `import { retry } from "@mongez/reinforcements"`. Skip: timing the retried op — `@warlock.js/core/benchmark-code/SKILL.md`; use-case-level `retry` option — `@warlock.js/core/write-use-case/SKILL.md`; competing libs `p-retry`, `async-retry`, `cockatiel`.
|
|
27
|
-
- [run-app](@warlock.js/core/run-app/SKILL.md): 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`; "start the dev server", "build for production", "run the bundle", "skip type generation", "tune watch globs", "dev server keyboard shortcuts", "press r to restart", "press q to quit", "restart the dev server", "port already in use"; typical config `warlock.config.ts > devServer / build`. Skip: writing a custom CLI — `@warlock.js/core/write-cli-command/SKILL.md`; config shape — `@warlock.js/core/configure-app/SKILL.md`; competing tooling `nodemon`, `tsx`, `ts-node-dev`, `esbuild` direct.
|
|
27
|
+
- [run-app](@warlock.js/core/run-app/SKILL.md): Three operational commands — `warlock dev` (HMR + type-gen + health checks), `warlock build` (esbuild bundle), `warlock start` (spawn the production bundle). All flags, all `warlock.config.ts` knobs that shape them. Triggers: `warlock dev`, `warlock build`, `warlock start`, `devServer`, `--fresh`, `--skip-typings`, `--skip-health`, `outdir`, `outFile`, `sourcemap`, `PortInUseError`, `assertPortIsAvailable`, `EADDRINUSE`, `EsbuildBinaryMissingError`; "start the dev server", "build for production", "run the bundle", "skip type generation", "tune watch globs", "dev server keyboard shortcuts", "press r to restart", "press q to quit", "restart the dev server", "port already in use"; typical config `warlock.config.ts > devServer / build`. Skip: writing a custom CLI — `@warlock.js/core/write-cli-command/SKILL.md`; config shape — `@warlock.js/core/configure-app/SKILL.md`; competing tooling `nodemon`, `tsx`, `ts-node-dev`, `esbuild` direct.
|
|
28
28
|
- [send-mail](@warlock.js/core/send-mail/SKILL.md): Send transactional email — `Mail` fluent builder, `sendMail()` direct call, React Email components. Test mode auto-captures into an in-memory mailbox; dev mode logs. Triggers: `Mail.to`, `sendMail`, `setMailMode`, `mailEvents`, `assertMailSent`, `getTestMailbox`, `wasMailSentTo`, `closeAllMailers`; "send a transactional email", "build a React Email template", "configure SMTP or SES", "assert an email was sent in tests"; typical import `import { Mail, sendMail } from "@warlock.js/core"`. Skip: per-config wiring — `@warlock.js/core/configure-app/SKILL.md`; layered service patterns — `@warlock.js/core/warlock-conventions/SKILL.md`; competing libs `nodemailer` direct, `@sendgrid/mail`, `resend`, `mailgun.js`.
|
|
29
29
|
- [send-response](@warlock.js/core/send-response/SKILL.md): 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`; "return a 201 from a controller", "send a file", "stream Server-Sent Events", "throw HTTP-shaped errors from services"; typical import `import type { RequestHandler, Response } from "@warlock.js/core"`. Skip: controller shape — `@warlock.js/core/create-controller/SKILL.md`; route registration — `@warlock.js/core/register-route/SKILL.md`; competing patterns: hand-rolled status codes via `reply.code(404).send(...)`, raw Fastify reply.
|
|
30
30
|
- [store-file](@warlock.js/core/store-file/SKILL.md): Read/write/delete files via the `storage` singleton — disks, drivers (local/S3/R2/DO Spaces), `storage.use(name)`, `StorageFile` handles, presigned URLs. Triggers: `storage.put`, `storage.get`, `storage.use`, `StorageFile`, `storageConfigurations`, `getPresignedUrl`, `getPresignedUploadUrl`; "save an uploaded file", "switch between local and S3", "generate a presigned URL", "read file metadata"; typical import `import { storage } from "@warlock.js/core"`. Skip: multipart parsing + image chain — `@warlock.js/core/upload-file/SKILL.md`; image transforms — `@warlock.js/core/process-image/SKILL.md`; storage config shape — `@warlock.js/core/configure-app/SKILL.md`; competing libs `@aws-sdk/client-s3`, `multer`, `formidable`.
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
- [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.
|
|
44
44
|
- [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`.
|
|
45
45
|
- [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`.
|
|
46
|
-
- [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
|
+
- [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`, `warlock add bull-board`, `index.register.ts`; "write a custom warlock command", "one-off maintenance task", "ship a CLI from a package", "framework built-in commands"; typical import `import { command } from "@warlock.js/core"`. Skip: framework dev/build/start — `@warlock.js/core/run-app/SKILL.md`; warlock.config.ts wiring — `@warlock.js/core/configure-app/SKILL.md`; competing libs `commander`, `yargs`, `oclif`.
|
|
47
47
|
- [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.
|
|
48
48
|
- [write-seeder](@warlock.js/core/write-seeder/SKILL.md): Author a seed file under `src/app/<module>/seeds/<name>.ts` using the `seeder()` factory — `name`, `dependsOn`, `once`, `order`, `batchSize`, `run({ track, now, batchSize })`. Auto-discovered by `warlock seed`; tracked in a `seeds` table; per-record refs in `seed_records` so `warlock seed --drop` can undo a seed. Triggers: `seeder`, `Seeder`, `SeedResult`, `SeedContext`, `SeedClock`, `track`, `now`, `batchSize`, `SeedersManager`, `warlock seed`, `--fresh`, `--drop`, `--list`, `--path`; "seed default roles", "undo a seed", "one-time data migration", "auto-discovered seeds", "order seeds by dependency", "deterministic seed timestamps", "inject a seed clock"; typical import `import { seeder } from "@warlock.js/core"`. Skip: module folder layout — `@warlock.js/core/create-module/SKILL.md`; repository CRUD — `@warlock.js/core/use-repository/SKILL.md`; CLI flags — `@warlock.js/core/write-cli-command/SKILL.md`; competing patterns: hand-rolled `node scripts/seed.js`, `typeorm-seeding`.
|
|
49
49
|
- [write-use-case](@warlock.js/core/write-use-case/SKILL.md): Author `useCase()` pipelines for business logic — guards, schema, before/after middleware, retry, benchmark, broadcast, lifecycle callbacks; transport-agnostic and observable by default. Input is inferred from the `schema`. Triggers: `useCase`, `UseCaseContext`, `UseCaseResult`, `retry`, `benchmark`, `broadcast`, `description`, `globalUseCasesEvents`, `UseCaseBroadcastChannel`; "encapsulate a business operation", "share logic between HTTP and CLI", "add guards and lifecycle hooks", "broadcast a use case result", "transport-agnostic pipeline"; typical import `import { useCase } from "@warlock.js/core"`. Skip: thin handler shape — `@warlock.js/core/create-controller/SKILL.md`; schema details — `@warlock.js/core/validate-input/SKILL.md`; the standalone retry util — `@warlock.js/core/retry-operation/SKILL.md`; competing libs `@nestjs/cqrs`, `inversify`, hand-rolled service classes.
|
package/package.json
CHANGED
|
@@ -25,13 +25,12 @@
|
|
|
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/
|
|
29
|
-
"@warlock.js/
|
|
30
|
-
"@warlock.js/
|
|
31
|
-
"@warlock.js/
|
|
32
|
-
"@warlock.js/
|
|
33
|
-
"@warlock.js/
|
|
34
|
-
"@warlock.js/fs": "5.12.0",
|
|
28
|
+
"@warlock.js/cache": "5.14.0",
|
|
29
|
+
"@warlock.js/cascade": "5.14.0",
|
|
30
|
+
"@warlock.js/context": "5.14.0",
|
|
31
|
+
"@warlock.js/logger": "5.14.0",
|
|
32
|
+
"@warlock.js/seal": "5.14.0",
|
|
33
|
+
"@warlock.js/fs": "5.14.0",
|
|
35
34
|
"chokidar": "^5.0.0",
|
|
36
35
|
"dayjs": "^1.11.19",
|
|
37
36
|
"es-module-lexer": "^2.0.0",
|
|
@@ -57,10 +56,10 @@
|
|
|
57
56
|
"react": "^19.2.3",
|
|
58
57
|
"react-dom": "^19.2.3",
|
|
59
58
|
"@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.
|
|
59
|
+
"@warlock.js/herald": "5.14.0",
|
|
60
|
+
"@warlock.js/ai": "5.14.0",
|
|
61
|
+
"@warlock.js/access": "5.14.0",
|
|
62
|
+
"@warlock.js/notifications": "5.14.0"
|
|
64
63
|
},
|
|
65
64
|
"peerDependenciesMeta": {
|
|
66
65
|
"sharp": {
|
|
@@ -123,7 +122,7 @@
|
|
|
123
122
|
],
|
|
124
123
|
"author": "hassanzohdy",
|
|
125
124
|
"license": "MIT",
|
|
126
|
-
"version": "5.
|
|
125
|
+
"version": "5.14.0",
|
|
127
126
|
"type": "module",
|
|
128
127
|
"main": "./esm/index.mjs",
|
|
129
128
|
"module": "./esm/index.mjs",
|
package/skills/run-app/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: run-app
|
|
3
|
-
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`; "start the dev server", "build for production", "run the bundle", "skip type generation", "tune watch globs", "dev server keyboard shortcuts", "press r to restart", "press q to quit", "restart the dev server", "port already in use"; typical config `warlock.config.ts > devServer / build`. Skip: writing a custom CLI — `@warlock.js/core/write-cli-command/SKILL.md`; config shape — `@warlock.js/core/configure-app/SKILL.md`; competing tooling `nodemon`, `tsx`, `ts-node-dev`, `esbuild` direct.'
|
|
3
|
+
description: 'Three operational commands — `warlock dev` (HMR + type-gen + health checks), `warlock build` (esbuild bundle), `warlock start` (spawn the production bundle). All flags, all `warlock.config.ts` knobs that shape them. Triggers: `warlock dev`, `warlock build`, `warlock start`, `devServer`, `--fresh`, `--skip-typings`, `--skip-health`, `outdir`, `outFile`, `sourcemap`, `PortInUseError`, `assertPortIsAvailable`, `EADDRINUSE`, `EsbuildBinaryMissingError`; "start the dev server", "build for production", "run the bundle", "skip type generation", "tune watch globs", "dev server keyboard shortcuts", "press r to restart", "press q to quit", "restart the dev server", "port already in use"; typical config `warlock.config.ts > devServer / build`. Skip: writing a custom CLI — `@warlock.js/core/write-cli-command/SKILL.md`; config shape — `@warlock.js/core/configure-app/SKILL.md`; competing tooling `nodemon`, `tsx`, `ts-node-dev`, `esbuild` direct.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Warlock — run the app
|
|
@@ -143,6 +143,7 @@ export default defineConfig({
|
|
|
143
143
|
restartOnConfigChange: true, // restart when warlock.config.ts / .env* changes
|
|
144
144
|
healthCheckers: [...] /* or false */,
|
|
145
145
|
transpileCacheDebug: false, // name cache files <slug>.<hash>.js w/ // @source markers
|
|
146
|
+
timings: false, // print a per-phase reload timing breakdown
|
|
146
147
|
},
|
|
147
148
|
});
|
|
148
149
|
```
|
|
@@ -153,6 +154,7 @@ export default defineConfig({
|
|
|
153
154
|
- **`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.
|
|
154
155
|
- **`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 [`update-packages/SKILL.md`](../update-packages/SKILL.md).
|
|
155
156
|
- **`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.
|
|
157
|
+
- **`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.
|
|
156
158
|
|
|
157
159
|
## `warlock build` — production bundle
|
|
158
160
|
|
|
@@ -258,7 +260,7 @@ Means `docker stop` / `kubectl delete pod` works as expected: SIGTERM reaches th
|
|
|
258
260
|
|
|
259
261
|
### pnpm needs esbuild's install script allowed
|
|
260
262
|
|
|
261
|
-
pnpm 10+ will not run a dependency's install script unless the app names it. esbuild's script links its platform-native binary, and `warlock build`
|
|
263
|
+
pnpm 10+ will not run a dependency's install script unless the app names it. esbuild's script links its platform-native binary, and both `warlock build` and `warlock dev` shell out to that binary — so the app installs cleanly and then cannot build or start dev:
|
|
262
264
|
|
|
263
265
|
```
|
|
264
266
|
[ERR_PNPM_IGNORED_BUILDS] Ignored build scripts: esbuild@0.27.7
|
|
@@ -273,6 +275,8 @@ allowBuilds:
|
|
|
273
275
|
|
|
274
276
|
Note pnpm reads this from `pnpm-workspace.yaml`, **not** from `package.json`'s `pnpm` field — pnpm 11 warns that the field is ignored and then carries on, so settings left there fail silently.
|
|
275
277
|
|
|
278
|
+
`warlock dev` checks for esbuild's native binary before starting (as `warlock build` already did) and fails fast with `EsbuildBinaryMissingError`, naming the same fix, instead of surfacing an opaque low-level error later from inside the bundler.
|
|
279
|
+
|
|
276
280
|
Nothing else is needed for pnpm. Warlock never requires an app to declare a package it does not import: generated code is checked at build time against the app's own `dependencies`, so `warlock build` failing over an unfamiliar package name is a framework bug, not a missing dependency.
|
|
277
281
|
|
|
278
282
|
### Output streams — what a supervisor may trust
|
|
@@ -20,7 +20,7 @@ import { groupedTranslations } from "@mongez/localization";
|
|
|
20
20
|
|
|
21
21
|
groupedTranslations("products", {
|
|
22
22
|
notFound: { en: "Product not found", ar: "المنتج غير موجود" },
|
|
23
|
-
created:
|
|
23
|
+
created: { en: "Product created", ar: "تم إنشاء المنتج" },
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
// 2. Look up in a controller / service
|
|
@@ -45,11 +45,11 @@ Every module owns its translation namespace under `src/app/<module>/utils/locale
|
|
|
45
45
|
import { groupedTranslations } from "@mongez/localization";
|
|
46
46
|
|
|
47
47
|
groupedTranslations("products", {
|
|
48
|
-
notFound:
|
|
49
|
-
outOfStock:
|
|
50
|
-
created:
|
|
51
|
-
updated:
|
|
52
|
-
deleted:
|
|
48
|
+
notFound: { en: "Product not found", ar: "المنتج غير موجود" },
|
|
49
|
+
outOfStock: { en: "Product out of stock", ar: "المنتج غير متوفر" },
|
|
50
|
+
created: { en: "Product created", ar: "تم إنشاء المنتج" },
|
|
51
|
+
updated: { en: "Product updated", ar: "تم تحديث المنتج" },
|
|
52
|
+
deleted: { en: "Product deleted", ar: "تم حذف المنتج" },
|
|
53
53
|
});
|
|
54
54
|
```
|
|
55
55
|
|
|
@@ -96,6 +96,10 @@ request.trans("products.notFound");
|
|
|
96
96
|
|
|
97
97
|
All three lookups go through `@mongez/localization`'s `trans()` under the hood, with the locale pulled from the request context (or the global default).
|
|
98
98
|
|
|
99
|
+
### Web `useTrans()` key checking
|
|
100
|
+
|
|
101
|
+
When an app uses `@warlock.js/web`, `warlock dev` writes `.warlock/typings/translations.d.ts` from literal `groupedTranslations("group", { key: ... })` registrations. It augments web's `TranslationKeyRegistry`, so `useTrans()("products.notFound")` is checked against registered keys and a typo fails TypeScript. Before the generated file exists, `useTrans()` accepts `string` for a non-breaking first boot. Dynamic groups/keys and placeholders are not inferred.
|
|
102
|
+
|
|
99
103
|
### Locale on a specific lookup
|
|
100
104
|
|
|
101
105
|
```ts
|
|
@@ -123,7 +127,7 @@ Configure the default:
|
|
|
123
127
|
|
|
124
128
|
```ts title="src/config/app.ts"
|
|
125
129
|
export default {
|
|
126
|
-
localeCode: "en",
|
|
130
|
+
localeCode: "en", // app-wide default
|
|
127
131
|
// ...
|
|
128
132
|
};
|
|
129
133
|
```
|
|
@@ -142,20 +146,19 @@ When a column stores per-locale values as an array:
|
|
|
142
146
|
|
|
143
147
|
```ts
|
|
144
148
|
// Schema (Seal):
|
|
145
|
-
name_translations: v.array(
|
|
149
|
+
name_translations: (v.array(
|
|
146
150
|
v.object({
|
|
147
|
-
localeCode: v.string(),
|
|
151
|
+
localeCode: v.string(), // "en", "ar", ...
|
|
148
152
|
value: v.string(),
|
|
149
|
-
})
|
|
153
|
+
}),
|
|
150
154
|
),
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
155
|
+
// Stored row (DB):
|
|
156
|
+
{
|
|
157
|
+
name_translations: [
|
|
158
|
+
{ localeCode: "en", value: "Hello World" },
|
|
159
|
+
{ localeCode: "ar", value: "مرحبا" },
|
|
160
|
+
],
|
|
161
|
+
});
|
|
159
162
|
```
|
|
160
163
|
|
|
161
164
|
Pick the right one for the current request:
|
|
@@ -179,12 +182,12 @@ getLocalized(
|
|
|
179
182
|
```
|
|
180
183
|
|
|
181
184
|
- **`values`** — the localized-array column.
|
|
182
|
-
- **`localeCode`**
|
|
183
|
-
- **`key`**
|
|
185
|
+
- **`localeCode`** _(optional)_ — pin to a specific locale. Defaults to the current request's locale (reads via `useRequestStore()`).
|
|
186
|
+
- **`key`** _(default `"value"`)_ — which property of the matched entry to return. Use a different key if your localized objects store the value under a different name.
|
|
184
187
|
|
|
185
188
|
```ts
|
|
186
189
|
const slug = getLocalized(product.get("slug_translations"), undefined, "value");
|
|
187
|
-
const tagline = getLocalized(product.get("name_translations"), "fr");
|
|
190
|
+
const tagline = getLocalized(product.get("name_translations"), "fr"); // force French
|
|
188
191
|
```
|
|
189
192
|
|
|
190
193
|
### Use inside a resource for clean per-locale responses
|
|
@@ -174,6 +174,30 @@ router.get("/analytics/summary", summaryController, {
|
|
|
174
174
|
|
|
175
175
|
`cacheKey` can be a string OR a function `(request) => string | Promise<string>` for per-request keys. Excludes failures and omits `["user", "settings"]` from the cached body by default.
|
|
176
176
|
|
|
177
|
+
### Tag-based invalidation
|
|
178
|
+
|
|
179
|
+
Give it `tags` — a static list, or a function of the request — to evict the entry early with `cache.tags([...]).invalidate()` (`@warlock.js/cache`), instead of waiting out `ttl`. Mirrors `route.cache.tags` on `@warlock.js/web`'s page cache, so an API response and a page can share the same tag and be invalidated together:
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
import { middleware } from "@warlock.js/core";
|
|
183
|
+
import { cache } from "@warlock.js/cache";
|
|
184
|
+
|
|
185
|
+
router.get("/orders/:id", getOrderController, {
|
|
186
|
+
middleware: [
|
|
187
|
+
middleware.cache({
|
|
188
|
+
cacheKey: (request) => `orders.${request.params.id}`,
|
|
189
|
+
ttl: 300,
|
|
190
|
+
tags: (request) => [`order.${request.params.id}`],
|
|
191
|
+
}),
|
|
192
|
+
],
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// Elsewhere, after the order changes:
|
|
196
|
+
await cache.tags([`order.${orderId}`]).invalidate();
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Untagged entries (no `tags` given) behave exactly as before — they only expire via `ttl`.
|
|
200
|
+
|
|
177
201
|
## Composed example
|
|
178
202
|
|
|
179
203
|
Tight cap on logins, concurrency + idempotency on AI calls:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: write-cli-command
|
|
3
|
-
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`, `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`.'
|
|
3
|
+
description: 'Author a custom `warlock <my-cmd>` command via the `command()` factory — name, description, action, options, preload, then register in `warlock.config.ts > cli.commands` or drop in `src/app/<module>/commands/`. Also covers built-in `warlock add` feature scaffolding, including the Web starter and `index.register.ts`. Triggers: `command`, `CLICommand`, `CLICommandPreload`, `CLICommandOption`, `preload`, `preAction`, `persistent`, `colors`, `warlock add`, `warlock add bull-board`, `index.register.ts`; "write a custom warlock command", "one-off maintenance task", "ship a CLI from a package", "framework built-in commands"; typical import `import { command } from "@warlock.js/core"`. Skip: framework dev/build/start — `@warlock.js/core/run-app/SKILL.md`; warlock.config.ts wiring — `@warlock.js/core/configure-app/SKILL.md`; competing libs `commander`, `yargs`, `oclif`.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Warlock — write a CLI command
|
|
@@ -207,6 +207,7 @@ warlock generate (alias: g) — interactive picker
|
|
|
207
207
|
| `react-email` | `react-email` + `@react-email/components` + `@react-email/render` + `@react-email/tailwind`; drops a `welcome-email.tsx` sample; patches `tsconfig.json` |
|
|
208
208
|
| `web` | Warlock Web + React stack; scaffolds the application page, localization, contact endpoint, and Web configuration |
|
|
209
209
|
| `react` | `react` + `react-dom` + types |
|
|
210
|
+
| `bull-board` | `@bull-board/api` + `@bull-board/fastify`; writes a `dashboard` block to `src/config/queue.ts`. `requires: ["queue"]` — adds the `queue` feature first automatically when it's missing |
|
|
210
211
|
| `image` | `sharp` (for the `Image` class) |
|
|
211
212
|
| `mail` | `nodemailer` + types |
|
|
212
213
|
| `ses` | `@aws-sdk/client-sesv2` |
|