@warlock.js/core 5.34.2 → 5.35.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 +62 -0
- package/esm/cli/cli-commands.manager.mjs +1 -1
- package/esm/cli/cli-commands.manager.mjs.map +1 -1
- package/esm/cli/commands/add.command.mjs +1 -0
- package/esm/cli/commands/add.command.mjs.map +1 -1
- package/esm/cli/commands/build.command.mjs +30 -3
- package/esm/cli/commands/build.command.mjs.map +1 -1
- package/esm/cli/commands/check/check-command.action.mjs +1 -0
- package/esm/cli/commands/check/check-command.action.mjs.map +1 -1
- package/esm/cli/commands/check.command.mjs +5 -0
- package/esm/cli/commands/check.command.mjs.map +1 -1
- package/esm/cli/commands/explain/explain-command.action.mjs +21 -0
- package/esm/cli/commands/explain/explain-command.action.mjs.map +1 -1
- package/esm/cli/commands/explain.command.mjs +14 -4
- package/esm/cli/commands/explain.command.mjs.map +1 -1
- package/esm/cli/commands/generate/generate.command.mjs +19 -1
- package/esm/cli/commands/generate/generate.command.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/endpoint.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/endpoint.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/web.generator.mjs +169 -0
- package/esm/cli/commands/generate/generators/web.generator.mjs.map +1 -0
- package/esm/cli/commands/generate/templates/web-stubs.mjs +231 -0
- package/esm/cli/commands/generate/templates/web-stubs.mjs.map +1 -0
- package/esm/cli/commands/inspect/inspect-command.action.mjs +4 -3
- package/esm/cli/commands/inspect/inspect-command.action.mjs.map +1 -1
- package/esm/cli/commands/inspect.command.mjs +13 -8
- package/esm/cli/commands/inspect.command.mjs.map +1 -1
- package/esm/cli/commands/mcp/mcp-command.action.mjs +1 -1
- package/esm/cli/commands/mcp/mcp-command.action.mjs.map +1 -1
- package/esm/config/config-loader.d.mts.map +1 -1
- package/esm/config/config-loader.mjs +2 -0
- package/esm/config/config-loader.mjs.map +1 -1
- package/esm/config/load-config-files.mjs +4 -0
- package/esm/config/load-config-files.mjs.map +1 -1
- package/esm/dev-server/file-event-handler.mjs +11 -1
- package/esm/dev-server/file-event-handler.mjs.map +1 -1
- package/esm/dev-server/file-manager.d.mts +1 -1
- package/esm/dev-server/file-manager.d.mts.map +1 -1
- package/esm/dev-server/file-manager.mjs.map +1 -1
- package/esm/dev-server/files-orchestrator.mjs +16 -1
- package/esm/dev-server/files-orchestrator.mjs.map +1 -1
- package/esm/dev-server/files-watcher.mjs +13 -4
- package/esm/dev-server/files-watcher.mjs.map +1 -1
- package/esm/dev-server/loader/loader-port-acks.mjs +21 -9
- package/esm/dev-server/loader/loader-port-acks.mjs.map +1 -1
- package/esm/dev-server/loader/register-loader.mjs +31 -12
- package/esm/dev-server/loader/register-loader.mjs.map +1 -1
- package/esm/dev-server/module-loader.mjs +14 -0
- package/esm/dev-server/module-loader.mjs.map +1 -1
- package/esm/dev-server/special-file-patterns.mjs +4 -1
- package/esm/dev-server/special-file-patterns.mjs.map +1 -1
- package/esm/e2e/browser.d.mts.map +1 -1
- package/esm/e2e/browser.mjs +3 -1
- package/esm/e2e/browser.mjs.map +1 -1
- package/esm/e2e/index.d.mts +2 -2
- package/esm/e2e/page.d.mts +6 -1
- package/esm/e2e/page.d.mts.map +1 -1
- package/esm/e2e/page.mjs +36 -1
- package/esm/e2e/page.mjs.map +1 -1
- package/esm/e2e/types.d.mts +37 -0
- package/esm/e2e/types.d.mts.map +1 -1
- package/esm/e2e/types.mjs.map +1 -1
- package/esm/errors/error-codes.d.mts +48 -0
- package/esm/errors/error-codes.d.mts.map +1 -1
- package/esm/errors/error-codes.mjs +48 -0
- package/esm/errors/error-codes.mjs.map +1 -1
- package/esm/errors/index.d.mts +2 -2
- package/esm/errors/index.mjs +2 -2
- package/esm/generations/add-command.action.mjs +2 -0
- package/esm/generations/add-command.action.mjs.map +1 -1
- package/esm/generations/design-system-payload.mjs +53 -0
- package/esm/generations/design-system-payload.mjs.map +1 -0
- package/esm/generations/features/design-system.feature.mjs +38 -0
- package/esm/generations/features/design-system.feature.mjs.map +1 -0
- package/esm/generations/features/index.mjs +3 -1
- package/esm/generations/features/index.mjs.map +1 -1
- package/esm/generations/features/notifications.feature.mjs +13 -2
- package/esm/generations/features/notifications.feature.mjs.map +1 -1
- package/esm/generations/features/test.feature.mjs +48 -13
- package/esm/generations/features/test.feature.mjs.map +1 -1
- package/esm/generations/stubs.mjs +9 -5
- package/esm/generations/stubs.mjs.map +1 -1
- package/esm/http/error-mapper.d.mts +1 -1
- package/esm/http/error-mapper.mjs +3 -3
- package/esm/http/error-mapper.mjs.map +1 -1
- package/esm/http/error-response.d.mts +15 -0
- package/esm/http/error-response.d.mts.map +1 -0
- package/esm/http/error-response.mjs +47 -0
- package/esm/http/error-response.mjs.map +1 -0
- package/esm/http/errors/errors.d.mts +8 -0
- package/esm/http/errors/errors.d.mts.map +1 -1
- package/esm/http/errors/errors.mjs +13 -1
- package/esm/http/errors/errors.mjs.map +1 -1
- package/esm/http/index.d.mts +5 -3
- package/esm/http/index.mjs +3 -2
- package/esm/http/list-endpoint.d.mts +35 -0
- package/esm/http/list-endpoint.d.mts.map +1 -0
- package/esm/http/list-endpoint.mjs +28 -0
- package/esm/http/list-endpoint.mjs.map +1 -0
- package/esm/http/middleware/inject-request-context.d.mts.map +1 -1
- package/esm/http/middleware/inject-request-context.mjs +12 -2
- package/esm/http/middleware/inject-request-context.mjs.map +1 -1
- package/esm/http/response.d.mts +2 -0
- package/esm/http/response.d.mts.map +1 -1
- package/esm/http/response.mjs +2 -0
- package/esm/http/response.mjs.map +1 -1
- package/esm/http/server.d.mts.map +1 -1
- package/esm/http/server.mjs +2 -0
- package/esm/http/server.mjs.map +1 -1
- package/esm/http/types.d.mts +7 -0
- package/esm/http/types.d.mts.map +1 -1
- package/esm/index.d.mts +10 -7
- package/esm/index.mjs +3 -2
- package/esm/openapi/security.mjs +12 -4
- package/esm/openapi/security.mjs.map +1 -1
- package/esm/openapi/types.d.mts +2 -0
- package/esm/openapi/types.d.mts.map +1 -1
- package/esm/production/build-budgets.d.mts +46 -0
- package/esm/production/build-budgets.d.mts.map +1 -0
- package/esm/production/build-budgets.mjs +109 -0
- package/esm/production/build-budgets.mjs.map +1 -0
- package/esm/production/production-builder.mjs +13 -1
- package/esm/production/production-builder.mjs.map +1 -1
- package/esm/production/resolve-build-config.d.mts +1 -1
- package/esm/production/resolve-build-config.d.mts.map +1 -1
- package/esm/production/resolve-build-config.mjs.map +1 -1
- package/esm/restful/restful.d.mts +1 -1
- package/esm/tests/fakes/storage-fake.d.mts +3 -1
- package/esm/tests/fakes/storage-fake.d.mts.map +1 -1
- package/esm/tests/fakes/storage-fake.mjs +3 -3
- package/esm/tests/fakes/storage-fake.mjs.map +1 -1
- package/esm/tests/fakes/test-fakes.d.mts +3 -1
- package/esm/tests/fakes/test-fakes.d.mts.map +1 -1
- package/esm/tests/fakes/test-fakes.mjs +3 -2
- package/esm/tests/fakes/test-fakes.mjs.map +1 -1
- package/esm/tests/index.d.mts +4 -2
- package/esm/tests/index.mjs +3 -1
- package/esm/tests/load-unit-config.mjs +24 -0
- package/esm/tests/load-unit-config.mjs.map +1 -0
- package/esm/tests/response-contract.d.mts +32 -0
- package/esm/tests/response-contract.d.mts.map +1 -0
- package/esm/tests/response-contract.mjs +116 -0
- package/esm/tests/response-contract.mjs.map +1 -0
- package/esm/tests/start-http-development-server.d.mts.map +1 -1
- package/esm/tests/start-http-development-server.mjs +10 -2
- 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-locales.mjs +33 -0
- package/esm/tests/test-locales.mjs.map +1 -0
- package/esm/tests/test-runtime-scope.d.mts +15 -0
- package/esm/tests/test-runtime-scope.d.mts.map +1 -0
- package/esm/tests/test-runtime-scope.mjs +80 -0
- package/esm/tests/test-runtime-scope.mjs.map +1 -0
- package/esm/tests/vitest-setup.d.mts +13 -3
- package/esm/tests/vitest-setup.d.mts.map +1 -1
- package/esm/tests/vitest-setup.mjs +146 -18
- package/esm/tests/vitest-setup.mjs.map +1 -1
- package/esm/tooling/check/affected-files.d.mts +5 -0
- package/esm/tooling/check/affected-files.d.mts.map +1 -0
- package/esm/tooling/check/affected-files.mjs +56 -0
- package/esm/tooling/check/affected-files.mjs.map +1 -0
- package/esm/tooling/check/changed-files.d.mts +2 -0
- package/esm/tooling/check/changed-files.d.mts.map +1 -1
- package/esm/tooling/check/changed-files.mjs +2 -2
- package/esm/tooling/check/changed-files.mjs.map +1 -1
- package/esm/tooling/check/conventions-step.d.mts +2 -1
- package/esm/tooling/check/conventions-step.d.mts.map +1 -1
- package/esm/tooling/check/conventions-step.mjs +48 -6
- package/esm/tooling/check/conventions-step.mjs.map +1 -1
- package/esm/tooling/check/fixes.d.mts +8 -0
- package/esm/tooling/check/fixes.d.mts.map +1 -0
- package/esm/tooling/check/fixes.mjs +31 -0
- package/esm/tooling/check/fixes.mjs.map +1 -0
- package/esm/tooling/check/index.d.mts +12 -0
- package/esm/tooling/check/index.mjs +3 -2
- package/esm/tooling/check/run-check.d.mts +2 -0
- package/esm/tooling/check/run-check.d.mts.map +1 -1
- package/esm/tooling/check/run-check.mjs +20 -4
- package/esm/tooling/check/run-check.mjs.map +1 -1
- package/esm/tooling/check/run-tests.mjs +1 -1
- package/esm/tooling/check/source-ast.d.mts +1 -0
- package/esm/tooling/check/web-conventions.d.mts +10 -0
- package/esm/tooling/check/web-conventions.d.mts.map +1 -0
- package/esm/tooling/check/web-conventions.mjs +126 -0
- package/esm/tooling/check/web-conventions.mjs.map +1 -0
- package/esm/tooling/index.d.mts +7 -2
- package/esm/tooling/index.mjs +4 -2
- package/esm/tooling/inspect/collect-files.mjs +172 -0
- package/esm/tooling/inspect/collect-files.mjs.map +1 -0
- package/esm/tooling/inspect/collect-pages.mjs +3 -2
- package/esm/tooling/inspect/collect-pages.mjs.map +1 -1
- package/esm/tooling/inspect/collect-routes.mjs +1 -1
- package/esm/tooling/inspect/collect-routes.mjs.map +1 -1
- package/esm/tooling/inspect/explain-file.d.mts +12 -0
- package/esm/tooling/inspect/explain-file.d.mts.map +1 -0
- package/esm/tooling/inspect/explain-file.mjs +45 -0
- package/esm/tooling/inspect/explain-file.mjs.map +1 -0
- package/esm/tooling/inspect/index.d.mts +3 -2
- package/esm/tooling/inspect/index.mjs +2 -1
- package/esm/tooling/inspect/inspect-app.d.mts.map +1 -1
- package/esm/tooling/inspect/inspect-app.mjs +9 -3
- package/esm/tooling/inspect/inspect-app.mjs.map +1 -1
- package/esm/tooling/inspect/inspect-report.schema.mjs +34 -1
- package/esm/tooling/inspect/inspect-report.schema.mjs.map +1 -1
- package/esm/tooling/inspect/inspect-report.types.d.mts +17 -1
- package/esm/tooling/inspect/inspect-report.types.d.mts.map +1 -1
- package/esm/tooling/inspect/inspect-report.types.mjs +2 -1
- package/esm/tooling/inspect/inspect-report.types.mjs.map +1 -1
- package/esm/tooling/mcp/mcp-tools.d.mts.map +1 -1
- package/esm/tooling/mcp/mcp-tools.mjs +8 -2
- package/esm/tooling/mcp/mcp-tools.mjs.map +1 -1
- package/esm/tooling/problem.d.mts +4 -0
- package/esm/tooling/problem.d.mts.map +1 -1
- package/esm/tooling/problem.mjs +1 -0
- package/esm/tooling/problem.mjs.map +1 -1
- package/esm/tooling/syntax/ast.d.mts +2 -0
- package/esm/tooling/typecheck/run-typecheck.mjs +5 -1
- package/esm/tooling/typecheck/run-typecheck.mjs.map +1 -1
- package/esm/upgrade/codemods/toolchain-templates.mjs +3 -1
- package/esm/upgrade/codemods/toolchain-templates.mjs.map +1 -1
- package/esm/vite/index.d.mts +3 -1
- package/esm/vite/index.mjs +3 -1
- package/esm/vite/test-setup-reporter.d.mts +16 -0
- package/esm/vite/test-setup-reporter.d.mts.map +1 -0
- package/esm/vite/test-setup-reporter.mjs +55 -0
- package/esm/vite/test-setup-reporter.mjs.map +1 -0
- package/esm/vite/test-workers.d.mts +5 -0
- package/esm/vite/test-workers.d.mts.map +1 -0
- package/esm/vite/test-workers.mjs +38 -0
- package/esm/vite/test-workers.mjs.map +1 -0
- package/esm/warlock-config/index.d.mts +2 -1
- package/esm/warlock-config/types.d.mts +3 -0
- package/esm/warlock-config/types.d.mts.map +1 -1
- package/llms-full.txt +883 -70
- package/llms.txt +58 -56
- package/package.json +15 -14
- package/schemas/inspect-report.schema.json +47 -1
- package/skills/build-budgets/SKILL.md +51 -0
- package/skills/build-restful/SKILL.md +56 -0
- package/skills/configure-app/SKILL.md +34 -0
- package/skills/create-module/SKILL.md +9 -0
- package/skills/generate-openapi/SKILL.md +1 -1
- package/skills/generate-web-ui/SKILL.md +71 -0
- package/skills/index.md +3 -3
- package/skills/run-app/SKILL.md +1 -1
- package/skills/send-mail/SKILL.md +25 -0
- package/skills/send-response/SKILL.md +77 -0
- package/skills/test-browser/SKILL.md +54 -0
- package/skills/test-http/SKILL.md +91 -0
- package/skills/test-service/SKILL.md +161 -3
- package/skills/upgrade-from-5-29/SKILL.md +22 -0
- package/skills/use-localization/SKILL.md +21 -0
- package/skills/warlock-check/SKILL.md +72 -1
- package/skills/warlock-inspect/SKILL.md +45 -2
- package/skills/warlock-mcp/SKILL.md +4 -0
- package/skills/warlock-trace/SKILL.md +2 -2
- package/skills/write-cli-command/SKILL.md +20 -2
- package/esm/production/build-app-production.mjs +0 -14
- package/esm/production/build-app-production.mjs.map +0 -1
|
@@ -458,3 +458,94 @@ This is fine for normal test flow. It bites when you're inside a transaction the
|
|
|
458
458
|
- The `create-controller` topic — the controller shape your HTTP tests are exercising.
|
|
459
459
|
- The `warlock-conventions` topic — module layout, where `tests/*.test.ts` files live.
|
|
460
460
|
- The `write-cli-command` topic — `warlock add test` scaffolds both global + worker setup files.
|
|
461
|
+
|
|
462
|
+
## Worker dictionaries and owned runtime resources
|
|
463
|
+
|
|
464
|
+
The generated `src/test-setup.ts` calls:
|
|
465
|
+
|
|
466
|
+
```ts
|
|
467
|
+
await setupTest({ importModule: (file) => import(file) });
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
`setupTest()` reads `src/app/*/utils/locales.json` after configuration in each
|
|
471
|
+
Vitest worker. Server translation helpers therefore see all configured locales
|
|
472
|
+
without manual registration. Invalid dictionaries fail setup. `teardownTest()`
|
|
473
|
+
unregisters those dictionaries; legacy executable locale files still require
|
|
474
|
+
explicit imports in worker setup.
|
|
475
|
+
|
|
476
|
+
Global HTTP fixtures should use `await startHttpTestServer({ port: 0, web: false })`
|
|
477
|
+
for API-only suites and `await stopHttpTestServer()` in teardown. Stop releases
|
|
478
|
+
connectors and the file runtime's loader channel, queued work, watchers, health
|
|
479
|
+
workers, and registered module cleanup hooks, including after partial startup.
|
|
480
|
+
A Node loader registration is process-scoped; its message channel is closed at
|
|
481
|
+
teardown. Module-owned timers/listeners must register their cleanup hooks.
|
|
482
|
+
|
|
483
|
+
A module that owns a long-running handle can export an awaited cleanup:
|
|
484
|
+
|
|
485
|
+
```ts
|
|
486
|
+
// src/app/messages/main.ts
|
|
487
|
+
import { createServer } from "node:net";
|
|
488
|
+
const listener = createServer();
|
|
489
|
+
listener.listen(0, "127.0.0.1");
|
|
490
|
+
export async function cleanup(): Promise<void> {
|
|
491
|
+
await new Promise<void>((resolve, reject) => {
|
|
492
|
+
listener.close((error) => (error ? reject(error) : resolve()));
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
HTTP test teardown awaits these cleanup functions and reports failures after
|
|
498
|
+
attempting every module's cleanup. Avoid leaving module-owned handles running
|
|
499
|
+
outside this lifecycle.
|
|
500
|
+
|
|
501
|
+
## Response contracts from declared schemas
|
|
502
|
+
|
|
503
|
+
`assertResponseContracts` from `@warlock.js/core/tests` sends HTTP requests and
|
|
504
|
+
asserts the serialized JSON body against the handler's `responseSchema` for the
|
|
505
|
+
actual status. It reuses Core's OpenAPI schema translation, including resource
|
|
506
|
+
classes, nested objects, arrays, nullable casts and resource self references.
|
|
507
|
+
It checks required fields and primitive types without coercion; extra fields
|
|
508
|
+
are allowed. URL/date format annotations are not checked beyond their declared
|
|
509
|
+
JSON shape. Builders, computed resolvers and resources without a static shape
|
|
510
|
+
fail with a diagnostic rather than silently passing.
|
|
511
|
+
|
|
512
|
+
```ts
|
|
513
|
+
import { it } from "vitest";
|
|
514
|
+
import { router } from "@warlock.js/core";
|
|
515
|
+
import { assertResponseContracts } from "@warlock.js/core/tests";
|
|
516
|
+
|
|
517
|
+
it("matches product response declarations", async () => {
|
|
518
|
+
await assertResponseContracts({
|
|
519
|
+
routes: router.list().filter((route) => route.path === "/products"),
|
|
520
|
+
cases: () => [{ path: "/products?page=1&limit=10", status: 200 }],
|
|
521
|
+
requireAllStatuses: true,
|
|
522
|
+
});
|
|
523
|
+
});
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
With the shared test server, retain `startHttpTestServer({ port: 0 })` in global
|
|
527
|
+
setup and `setupTest` in the worker. The routes and their handler schemas must
|
|
528
|
+
also be loaded in the worker running this assertion (import their routes module
|
|
529
|
+
there); global setup runs in a different process. Omit `routes` to discover all
|
|
530
|
+
registered routes with `responseSchema` in that worker. Empty discovery fails.
|
|
531
|
+
Explicit routes lacking a schema also fail.
|
|
532
|
+
|
|
533
|
+
Static GET routes default to one request without headers. Parameterized routes
|
|
534
|
+
and non-GET methods require explicit `cases(route)` fixtures; an empty case
|
|
535
|
+
list fails. Each case can supply a concrete `path`, `init` (headers, serialized
|
|
536
|
+
body, etc.) and expected `status`. Supply fixtures with valid IDs, seeded data,
|
|
537
|
+
authentication and invalid inputs to exercise the desired outcomes. An `all` route also needs a concrete fixture `method`. Redirects
|
|
538
|
+
are not followed. POST/PUT/PATCH/DELETE fixtures execute real side effects;
|
|
539
|
+
use isolated test data and clean it up.
|
|
540
|
+
|
|
541
|
+
Undeclared response statuses fail. Only statuses actually returned are checked
|
|
542
|
+
by default; `requireAllStatuses: true` additionally fails if any declared status
|
|
543
|
+
has no exercised fixture. HEAD, 204 and 304 responses must have an empty body; declare it with
|
|
544
|
+
`{ body: {} }`. Other statuses must carry matching JSON.
|
|
545
|
+
|
|
546
|
+
For an in-process server, pass `client: app` from `createTestHttpServer()` and
|
|
547
|
+
close it in teardown. For signed-in requests, pass `client: await actingAs(user)`
|
|
548
|
+
and dispose that client afterward. These clients use the same assertion and
|
|
549
|
+
run the real HTTP middleware and serialization paths.
|
|
550
|
+
|
|
551
|
+
Cleanup hooks that own asynchronous handles should return a promise for completed closure. For MessagePorts, subscribe to `close` before calling `close()` and await the event before checking reference state.
|
|
@@ -13,9 +13,9 @@ For unit tests, you import the thing under test and call it directly. No HTTP, n
|
|
|
13
13
|
|
|
14
14
|
⛔ **If your project was generated before 4.14.0, fix BOTH the comment and the call.** The comment is false, **and** the generated `setupTest({ connectors: true })` is now an _explicit_ value that overrides your `src/config/tests.ts`. **Bare `setupTest()` is the correct call.**
|
|
15
15
|
|
|
16
|
-
**The lifetime is FILE-SCOPED
|
|
16
|
+
**The default lifetime is FILE-SCOPED.** Your setup file bootstraps the framework and its `afterAll(teardownTest)` closes it, once per test file. **One owner, one pairing — correct under every pool, every isolation setting, and watch mode.**
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Worker lifetime is available as an opt-in in 5.35.0. See the runtime lifetime section below for its runner, pool and isolation requirements.
|
|
19
19
|
|
|
20
20
|
⚠ **Changed in 4.13.0 — the import is a subpath now.** `setupTest` used to be re-exported from the package root; it is not any more, because that put the test helpers into every application's production module graph. `import { setupTest } from "@warlock.js/core"` now fails with _"has no exported member"_ — **add `/tests` to the specifier and nothing else changes.**
|
|
21
21
|
|
|
@@ -417,7 +417,7 @@ Node process, preserve the source package's module mode. ESM fixtures need a
|
|
|
417
417
|
CommonJS and named exports fail before the behavior under test runs. Assert the
|
|
418
418
|
child process exit status with its captured stderr before checking stdout.
|
|
419
419
|
|
|
420
|
-
-
|
|
420
|
+
- **By default `setupTest` boots per test file** — every version of this skill through 4.13.0 said otherwise. **You pay one framework bootstrap per test file**, which is what 4.13.0 already cost; the difference is that it is now a chosen lifetime rather than a side effect of a module flag resetting.
|
|
421
421
|
- ⛔ **Never delete the `afterAll(teardownTest)` from your setup file.** Without it nothing closes what `setupTest` opened, and the connectors outlive the file that started them.
|
|
422
422
|
- ⛔ **You can't swap the connector set by calling `setupTest` again — it rejects now.** Through 4.13.0 the second call was silently ignored. Tear down first, or don't call it.
|
|
423
423
|
- **These connections are separate from the HTTP test server's.** A row inserted by a service-level test is on this connection; the HTTP test server has its own. They only see each other if both point at the same physical DB **and** the inserting test has committed.
|
|
@@ -444,3 +444,161 @@ setupTest({ importModule: (file) => import(file) });
|
|
|
444
444
|
```
|
|
445
445
|
|
|
446
446
|
The generated `src/test-setup.ts` already does this. Without it, `setupTest()` under Vitest warns once.
|
|
447
|
+
|
|
448
|
+
## Runtime lifetime, unit projects and setup profiling
|
|
449
|
+
|
|
450
|
+
`warlock add test` (also used by `create-warlock --features=test`) generates two
|
|
451
|
+
Vitest projects. `unit` discovers `src/**/*.spec.ts` outside `tests/` directories
|
|
452
|
+
and has no Warlock setup or HTTP global setup. `integration` discovers
|
|
453
|
+
`src/**/*.test.ts`, specs inside `src/**/tests/`, and `tests/**/*.{test,spec}.ts`.
|
|
454
|
+
It uses the framework setup, HTTP global setup and a generated `src/test-runner.ts`.
|
|
455
|
+
Keep pure service specs beside their source and mock repositories at the boundary.
|
|
456
|
+
Existing config files are preserved; copy the projects layout into them manually.
|
|
457
|
+
Vitest 4.1.10 or newer is required for the generated runner.
|
|
458
|
+
|
|
459
|
+
For a unit spec that needs configuration values, use:
|
|
460
|
+
|
|
461
|
+
```ts
|
|
462
|
+
import { afterAll, expect } from "vitest";
|
|
463
|
+
import { setupTest, teardownTest } from "@warlock.js/core/tests";
|
|
464
|
+
|
|
465
|
+
await setupTest({
|
|
466
|
+
mode: "unit",
|
|
467
|
+
importModule: (file) => import(file),
|
|
468
|
+
file: expect.getState().testPath,
|
|
469
|
+
});
|
|
470
|
+
afterAll(teardownTest);
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
Unit mode loads `warlock.config.ts` and configuration values once per module graph.
|
|
474
|
+
It skips bootstrap/env/prestart hooks, connectors, config special handlers,
|
|
475
|
+
`filesOrchestrator.init()`, the native ESM loader, and fake installation. Keep
|
|
476
|
+
configuration imports free of side effects; arbitrary code imported by a config
|
|
477
|
+
file can still perform I/O. A plain unit spec usually needs no `setupTest()` at all.
|
|
478
|
+
`connectors: false` still bootstraps; it is not the cheap unit mode. Use separate
|
|
479
|
+
projects for unit and integration runtimes.
|
|
480
|
+
|
|
481
|
+
### Opt into one runtime per fork
|
|
482
|
+
|
|
483
|
+
The default remains `tests.lifetime: "file"`. To reuse a runtime, change the
|
|
484
|
+
integration project's `isolate` to `false`, keep `pool: "forks"` and
|
|
485
|
+
`runner: "./src/test-runner.ts"`, then configure:
|
|
486
|
+
|
|
487
|
+
```ts title="src/config/tests.ts"
|
|
488
|
+
import { resetWorkerDatabase } from "../test-database";
|
|
489
|
+
|
|
490
|
+
export default {
|
|
491
|
+
lifetime: "worker",
|
|
492
|
+
// Application-owned callback: truncate only this worker's test database.
|
|
493
|
+
// Called before every file's fixtures, including the first file.
|
|
494
|
+
resetBetweenFiles: async () => {
|
|
495
|
+
await resetWorkerDatabase();
|
|
496
|
+
},
|
|
497
|
+
profileSetup: true,
|
|
498
|
+
};
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
Run with `npx vitest run --project integration`. Worker lifetime refuses watch,
|
|
502
|
+
threads, isolated module graphs, or a missing runner with a message explaining
|
|
503
|
+
the required settings. Keep `afterAll(teardownTest)` in the setup file: in worker
|
|
504
|
+
mode it marks the end of the file; Vitest's awaited worker cleanup closes the
|
|
505
|
+
runtime once. The runner uses `VitestTestRunner.onCleanupWorkerContext`, verified
|
|
506
|
+
in Vitest 4.1.10's `runners.d.ts`, runner implementation and worker cleanup source.
|
|
507
|
+
For an existing project, generate this runner without overwriting your config:
|
|
508
|
+
|
|
509
|
+
```ts title="src/test-runner.ts"
|
|
510
|
+
import { configureTestWorker } from "@warlock.js/core/tests";
|
|
511
|
+
import { VitestTestRunner } from "vitest/runners";
|
|
512
|
+
|
|
513
|
+
export default class WarlockTestRunner extends VitestTestRunner {
|
|
514
|
+
public constructor(config: ConstructorParameters<typeof VitestTestRunner>[0]) {
|
|
515
|
+
super(config);
|
|
516
|
+
configureTestWorker(
|
|
517
|
+
{ pool: this.pool, watch: config.watch, isolate: config.isolate },
|
|
518
|
+
(cleanup) => this.onCleanupWorkerContext(cleanup),
|
|
519
|
+
);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
The first file bootstraps; subsequent files reuse connectors and config. Between
|
|
525
|
+
files, selected fakes are restored and reinstalled, resetting mail/queue records,
|
|
526
|
+
cache, secrets, clock, IDs and a private storage directory. Worker storage is
|
|
527
|
+
separate from the global HTTP server's storage: use an in-process test HTTP server
|
|
528
|
+
when assertions need to see request-side fake state. The hook runs after fake
|
|
529
|
+
reset and before fixtures. It must finish before returning. Within a file,
|
|
530
|
+
repeated `setupTest()` calls remain idempotent; use `beforeEach`/`afterEach` for
|
|
531
|
+
per-test cleanup.
|
|
532
|
+
|
|
533
|
+
This trades module isolation for startup cost: application singletons, config
|
|
534
|
+
mutations, mocks and module side effects can survive between files. Reset your
|
|
535
|
+
own state in `resetBetweenFiles`, restore mocks, and keep connector selection
|
|
536
|
+
consistent. Give each worker a distinct database/schema using
|
|
537
|
+
`process.env.VITEST_POOL_ID` when preparing test connections. Never drop a shared
|
|
538
|
+
database from this hook while other workers are using it. The framework does not
|
|
539
|
+
create a memory replica set or a cross-worker lock; those belong to the application's
|
|
540
|
+
global setup. A shared HTTP server and a single replica set can contend on I/O,
|
|
541
|
+
locks and shared fixtures even though workers run concurrently. Scope rows and
|
|
542
|
+
HTTP fixtures per worker, or run tests that require global mutation separately
|
|
543
|
+
with `maxWorkers: 1`. No test-server teardown ownership changes are needed here.
|
|
544
|
+
|
|
545
|
+
`getTestRuntimeStats()` from `@warlock.js/core/tests` returns process-local
|
|
546
|
+
`{ bootstraps, files }`. For example, after setup in worker mode:
|
|
547
|
+
|
|
548
|
+
```ts
|
|
549
|
+
import { expect, it } from "vitest";
|
|
550
|
+
import { getTestRuntimeStats } from "@warlock.js/core/tests";
|
|
551
|
+
|
|
552
|
+
it("reuses this worker's runtime", () => {
|
|
553
|
+
expect(getTestRuntimeStats().bootstraps).toBe(1);
|
|
554
|
+
});
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
Across one integration project, a successful run with no worker recycling needs
|
|
558
|
+
at most `maxWorkers` bootstraps. Multiple projects, worker crashes and memory-limit
|
|
559
|
+
recycling can create additional processes; count distinct PIDs in profiles.
|
|
560
|
+
|
|
561
|
+
### Measure and size CI workers
|
|
562
|
+
|
|
563
|
+
Set `tests.profileSetup: true` or run
|
|
564
|
+
`WARLOCK_TEST_PROFILE=1 npx vitest run --project integration`. Pass
|
|
565
|
+
`file: expect.getState().testPath` to `setupTest()` for file labels (the generated
|
|
566
|
+
setup does this). Each file emits one line with milliseconds for environment, config,
|
|
567
|
+
bootstrap, orchestrator, app config, connectors, fakes, reset and teardown as
|
|
568
|
+
applicable. Reused files report reset instead of startup steps. A summary per
|
|
569
|
+
worker reports file/bootstrap counts, summed step timings and final shutdown.
|
|
570
|
+
The generated config also installs `TestSetupReporter` from `@warlock.js/core/vite`
|
|
571
|
+
(`reporters: ["default", new TestSetupReporter()]`), which aggregates file counts,
|
|
572
|
+
bootstrap counts and timings across PIDs into a run summary. Summed timings are
|
|
573
|
+
not wall time. Worker shutdown is included when its summary reaches the reporter
|
|
574
|
+
before the run-end callback; individual worker summaries always report it.
|
|
575
|
+
|
|
576
|
+
The generated config sets `maxWorkers: recommendedTestWorkers()` from
|
|
577
|
+
`@warlock.js/core/vite`. It takes the smaller of CPU affinity and the tightest
|
|
578
|
+
visible cgroup v2 quota, rounding fractional CPUs down with a minimum of one.
|
|
579
|
+
For example `cpu.max = 1200000 100000` recommends 12 workers on a 48-CPU host.
|
|
580
|
+
The format follows the [kernel cgroup v2 CPU interface](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html#cpu-interface-files).
|
|
581
|
+
It reads `/proc/self/cgroup` and visible ancestors under `/sys/fs/cgroup`; hosts
|
|
582
|
+
without readable v2 quotas use affinity. Set `maxWorkers` explicitly on cgroup v1,
|
|
583
|
+
custom cgroup mounts, or when database/memory limits require fewer workers.
|
|
584
|
+
|
|
585
|
+
### Release gate
|
|
586
|
+
|
|
587
|
+
```bash
|
|
588
|
+
npx warlock test --changed --since "$LAST_RELEASE_REF"
|
|
589
|
+
npx vitest run --project integration
|
|
590
|
+
# Nightly (all projects):
|
|
591
|
+
npx vitest run
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
The first command includes affected tests, using the existing changed-test CLI;
|
|
595
|
+
the second always covers integration wiring. Keep the full suite nightly and
|
|
596
|
+
compare cold and reused setup profiles on the same revision, worker count and
|
|
597
|
+
database fixture before claiming a speedup.
|
|
598
|
+
|
|
599
|
+
For a manual fake harness outside `setupTest`, the same private storage behavior
|
|
600
|
+
is available with `await installTestFakes(true, { isolatedStorage: true })`, paired
|
|
601
|
+
with `await restoreTestFakes()`. Both are exported from `@warlock.js/core/tests`.
|
|
602
|
+
`await storageFake.install({ isolated: true })` / `await storageFake.restore()`
|
|
603
|
+
provides it for a storage-only harness. Existing installs share the HTTP root by
|
|
604
|
+
default; the isolated option never replaces or deletes that shared root.
|
|
@@ -476,6 +476,10 @@ It replaces standard scripts/dependencies, pins TypeScript 7.0.2, updates genera
|
|
|
476
476
|
editor settings, removes `healthCheckers.eslint` and selects Oxlint. A generated
|
|
477
477
|
`.prettierignore` becomes `.oxfmtignore`; Oxfmt scripts read it explicitly.
|
|
478
478
|
|
|
479
|
+
Generated migration configs enable `typescript/no-explicit-any`, `curly`, and
|
|
480
|
+
`no-console` as errors, matching new apps. Fix those diagnostics before running
|
|
481
|
+
`npm run lint:check` and `npx warlock check` again.
|
|
482
|
+
|
|
479
483
|
The `oxc-toolchain` codemod also updates generated VS Code settings and literal
|
|
480
484
|
ESLint/Oxlint health-check switches. Custom editor settings, checker arrays,
|
|
481
485
|
computed options and nonstandard scripts require review. Oxc diagnostics keep
|
|
@@ -530,3 +534,21 @@ editor settings and nonstandard scripts can also require review.
|
|
|
530
534
|
existing Oxc configs retain their categories. A real lockfile beside a workspace
|
|
531
535
|
marker determines the installer: `package-lock.json` plus `pnpm-workspace.yaml`
|
|
532
536
|
without `pnpm-lock.yaml` now produces `npm install`.
|
|
537
|
+
|
|
538
|
+
## 5.34 to 5.35 resource hidden input
|
|
539
|
+
|
|
540
|
+
Model resources now receive hidden input columns (subject to `resourceColumns`)
|
|
541
|
+
to support derivations such as `has_secret: Boolean(data.secret)`. Model
|
|
542
|
+
serialization removes `hidden` top-level keys from the final resource result.
|
|
543
|
+
Review resources that copy input under renamed or nested keys and return explicit
|
|
544
|
+
public projections. Direct resource construction does not invoke model filtering.
|
|
545
|
+
|
|
546
|
+
## 5.34 to 5.35 document hydration
|
|
547
|
+
|
|
548
|
+
Initial Web hydration now includes `root.tsx`, matching the document ancestry
|
|
549
|
+
used by SSR so `useId()` and generated Mongez form IDs agree beneath layouts.
|
|
550
|
+
Root components and providers execute in both realms. Move server-only work into
|
|
551
|
+
`root.setup.ts` loaders and pass browser-safe results as `data`; retain exactly
|
|
552
|
+
one `#vessel` around `{children}`. Client navigation still swaps layout/page
|
|
553
|
+
children while preserving the document root. Remove temporary explicit form IDs
|
|
554
|
+
only when the application does not otherwise depend on those names.
|
|
@@ -336,3 +336,24 @@ GET /products/42?locale=ar
|
|
|
336
336
|
This produces `account.title` and `account.actions.save`. Keep every leaf complete for the configured locale list. The page pipeline selects an immutable snapshot for its route source and locale. `useTrans()` and `t()` use that snapshot; a missing scoped key returns the key itself. With no route-locales manifest, the existing global `@mongez/localization` registry remains the legacy fallback path.
|
|
337
337
|
|
|
338
338
|
When a route-locales snapshot applies, `t()` (through the request binding) and `request.transFrom(locale, key, placeholders?)` resolve through it; without one, they retain the existing global-registry behavior. The underlying `transFromKeywords(locale, keywords, key, placeholders?, converter?)` is supplied by `@mongez/localization` 3.5.0. Error pages rebind to their own snapshot, while framework fallback uses the app/root snapshot. Development HMR add/edit/delete publishes a new snapshot, and the snapshot revision keeps page-cache entries from reusing old JSON. Generated `.warlock` typings contain the flattened route keys; do not maintain a second handwritten key union.
|
|
339
|
+
|
|
340
|
+
## Worker dictionaries and owned runtime resources
|
|
341
|
+
|
|
342
|
+
The generated `src/test-setup.ts` calls:
|
|
343
|
+
|
|
344
|
+
```ts
|
|
345
|
+
await setupTest({ importModule: (file) => import(file) });
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
`setupTest()` reads `src/app/*/utils/locales.json` after configuration in each
|
|
349
|
+
Vitest worker. Server translation helpers therefore see all configured locales
|
|
350
|
+
without manual registration. Invalid dictionaries fail setup. `teardownTest()`
|
|
351
|
+
unregisters those dictionaries; legacy executable locale files still require
|
|
352
|
+
explicit imports in worker setup.
|
|
353
|
+
|
|
354
|
+
Global HTTP fixtures should use `await startHttpTestServer({ port: 0, web: false })`
|
|
355
|
+
for API-only suites and `await stopHttpTestServer()` in teardown. Stop releases
|
|
356
|
+
connectors and the file runtime's loader channel, queued work, watchers, health
|
|
357
|
+
workers, and registered module cleanup hooks, including after partial startup.
|
|
358
|
+
A Node loader registration is process-scoped; its message channel is closed at
|
|
359
|
+
teardown. Module-owned timers/listeners must register their cleanup hooks.
|
|
@@ -75,7 +75,7 @@ npx warlock typecheck --changed # changed files + the files importing them
|
|
|
75
75
|
npx warlock typecheck --json --project tsconfig.app.json
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
`--changed` checks
|
|
78
|
+
`--changed` checks diagnostics for changed files and their transitive importers. The native compiler still performs an incremental program compilation.
|
|
79
79
|
|
|
80
80
|
## `warlock explain`
|
|
81
81
|
|
|
@@ -135,3 +135,74 @@ const types = runTypecheck({ files: ["src/app/posts/services/publish.service.ts"
|
|
|
135
135
|
Migrate lint and format tooling with
|
|
136
136
|
`npx warlock upgrade --from 5.32 --to 5.33.0 --dry-run`, then remove `--dry-run`
|
|
137
137
|
and work through the manual-review list. Use `--lint=oxc` for new apps.
|
|
138
|
+
|
|
139
|
+
## Web and response contract conventions
|
|
140
|
+
|
|
141
|
+
The following codes default to **warnings**, so upgrading does not fail existing projects.
|
|
142
|
+
They parse real TypeScript/JSX syntax with the same oxc-parser adapter as the existing conventions.
|
|
143
|
+
|
|
144
|
+
| Code | Convention | Remedy |
|
|
145
|
+
| -------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
146
|
+
| `WL9013` | A component file exceeds 150 lines | Split components and extract hooks; configure `componentLineLimit`. |
|
|
147
|
+
| `WL9014` | More than one component in a file | Move each component into its own TSX file. |
|
|
148
|
+
| `WL9015` | State/effects or event-handler functions inside a component | Move `useState`, `useReducer`, `useEffect`, `useLayoutEffect` and handlers into `use-*.ts` hooks. |
|
|
149
|
+
| `WL9016` | Native select, checkbox, radio, date, time or datetime-local input | Use the design-system control. Native controls are allowed in `src/web/design-system/**`. |
|
|
150
|
+
| `WL9017` | DOM input/textarea/select native validation | Use shared schema validation instead of `required`, `pattern`, `min`, `max`, `minLength`, `maxLength` or input `type="email"`. Custom component props are allowed. |
|
|
151
|
+
| `WL9018` | Exported `RequestHandler` in `src/app/**/controllers` lacks `responseSchema` | Assign `handler.responseSchema` to document each response status. |
|
|
152
|
+
|
|
153
|
+
Web rules apply to `src/web/**/*.tsx`. Components are top-level JSX-returning functions
|
|
154
|
+
with a capitalized name (or an anonymous default export). Hook files and ordinary helpers
|
|
155
|
+
are excluded. Handler checks recognize inline JSX callbacks, `handle*`/`on*` functions,
|
|
156
|
+
and local function values referenced by event props. They do not execute code or infer
|
|
157
|
+
runtime spreads, factory contracts or values imported from other files.
|
|
158
|
+
|
|
159
|
+
Create `.warlock-check.json` in the project root:
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"componentLineLimit": 180,
|
|
164
|
+
"rules": {
|
|
165
|
+
"WL9013": "warning",
|
|
166
|
+
"WL9015": "error",
|
|
167
|
+
"WL9016": "off"
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
`rules` accepts `"off"`, `"warning"`, or `"error"` for convention codes, including
|
|
173
|
+
existing codes. Per-line `// warlock-check-ignore WL9015 -- reason` works as before.
|
|
174
|
+
Use `npx warlock explain WL9015` for the registry explanation.
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
npx warlock check --changed --fix --json
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
`--changed` selects tracked changes against HEAD plus untracked source files and their
|
|
181
|
+
transitive import dependents (including re-exports, type imports and related tests).
|
|
182
|
+
Resolution uses the project's compiler configuration, with relative/app imports as a
|
|
183
|
+
fallback for files outside that configuration. Lint and conventions receive that selection;
|
|
184
|
+
Vitest uses related mode. TypeScript still compiles incrementally as a program, then filters
|
|
185
|
+
diagnostics to the selection and its importers; this is not a partial compilation.
|
|
186
|
+
|
|
187
|
+
`--fix` applies safe convention edits before the pipeline. Currently it removes `.js`
|
|
188
|
+
suffixes from relative imports (`WL9002`). Ignored/disabled findings are not fixed.
|
|
189
|
+
Component extraction, control replacement and response schemas require human decisions.
|
|
190
|
+
Problems that have a safe edit include optional `fix: { start, end, text }` in JSON;
|
|
191
|
+
`start` and `end` are zero-based source string offsets with an exclusive end.
|
|
192
|
+
The report otherwise keeps schema version 1 and its existing shape. Applied fixes disappear
|
|
193
|
+
from the final report; unresolved findings remain. Review the resulting source diff.
|
|
194
|
+
|
|
195
|
+
Programmatic usage: `await runCheck({ changed: true, fix: true })` from
|
|
196
|
+
`@warlock.js/core/tooling`.
|
|
197
|
+
|
|
198
|
+
## Explain a source file
|
|
199
|
+
|
|
200
|
+
`npx warlock explain src/app/posts/services/list.service.ts --json` reports the file's module, convention role, exports, imports, importers and reaching routes/pages. It boots the app for route/page registrations; error-code explanations remain static. See the `warlock-inspect` topic for graph semantics and the boot-free `npx warlock inspect --section files --json` command.
|
|
201
|
+
|
|
202
|
+
Starter controllers declare a response contract for each returned status. For example:
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
contactController.responseSchema = { 200: { body: { message: "string" } } };
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Use `npx warlock inspect --section files --json` for static inspection without booting the app; `npx warlock explain src/app/contact/controllers/contact.controller.ts` explains its entry points.
|
|
@@ -13,9 +13,9 @@ npx warlock inspect --json > app.json # the full report
|
|
|
13
13
|
npx warlock inspect --json --section routes,models # only some sections
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Except for `--section files` (static source inspection without app boot), it boots like `warlock doctor`: connectors boot (routes register) but none starts — no database, cache or socket connection, no port. With `--json`, stdout is only the JSON.
|
|
17
17
|
|
|
18
|
-
Sections: `routes`, `models`, `resources`, `config`, `events`, `pages`, `jobs`, `schedules`, `packages`. An unknown section fails before the app boots.
|
|
18
|
+
Sections: `routes`, `models`, `resources`, `config`, `events`, `pages`, `jobs`, `schedules`, `packages`, `files`. An unknown section fails before the app boots.
|
|
19
19
|
|
|
20
20
|
## Answer questions with jq
|
|
21
21
|
|
|
@@ -132,3 +132,46 @@ const valid = new Ajv2020({ strict: false }).validate(INSPECT_REPORT_JSON_SCHEMA
|
|
|
132
132
|
- The `warlock-agents-md` topic — the app summary `warlock dev` keeps in AGENTS.md.
|
|
133
133
|
- The `warlock-routes` topic — the human route table.
|
|
134
134
|
- The `generate-openapi` topic — the same route schemas as an OpenAPI document.
|
|
135
|
+
|
|
136
|
+
## Session middleware in groups
|
|
137
|
+
|
|
138
|
+
`sessionMiddleware({ userTypes: "user" })` publishes the same `warlock.auth`
|
|
139
|
+
descriptor as `authMiddleware()`. Group middleware is inherited by nested
|
|
140
|
+
routes, so `inspect` and the generated `agents-md` summary recognize these guards.
|
|
141
|
+
`{ optional: true }` reports `auth.required: false`, with sources and user types
|
|
142
|
+
retained. Such routes remain in the unguarded-write list. Legacy descriptors
|
|
143
|
+
without `required` still mean required authentication.
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
import { router } from "@warlock.js/core";
|
|
147
|
+
import { sessionMiddleware } from "@warlock.js/auth";
|
|
148
|
+
|
|
149
|
+
router.group({ middleware: [sessionMiddleware({ userTypes: "user" })] }, () => {
|
|
150
|
+
router.post("/settings", async ({ response }) => response.success({ saved: true }));
|
|
151
|
+
});
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Source files and reachability
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
npx warlock inspect --section files --json
|
|
158
|
+
npx warlock explain src/app/posts/services/list.service.ts
|
|
159
|
+
npx warlock explain src/web/components/Post.tsx --json
|
|
160
|
+
npx warlock explain WL3001 --json
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The `files` section reads every file under `src/`, without importing app modules or booting connectors. Each entry has `file`, `module`, `role`, `exports`, `imports` and `importedBy`. Paths are relative to the project root. Modules use `src/app/<module>` or the containing top-level `src` directory. Roles follow file names and directories: controller, service, repository, model, migration, schema, resource, routes, page, setup, layout, root, hook, component, util, type, config and spec; unmatched files use `source`. Non-code assets have empty exports and imports.
|
|
164
|
+
|
|
165
|
+
Each code file is parsed once with OXC per inspection. Export names include types, aliases, destructured bindings, `default` and `*` for star re-exports; star exports are recorded rather than expanded. Imports include type imports, side effects, re-exports and literal dynamic imports. Each import is `{ specifier, file }`: `file` is the resolved local path, or `null` for external/unresolved imports. Resolution follows inherited tsconfig path aliases, fallback targets, baseUrl, extensionless files and directory indexes within `src/`. Computed dynamic imports and CommonJS `require()` calls are not graph edges. Parse/config failures appear in `warnings`.
|
|
166
|
+
|
|
167
|
+
File explanations accept a project-relative or absolute path. They boot the app to read the existing routes/pages sections, then walk the static graph to find entry points reaching the file, including page layouts and loaders. Type-only edges participate; this is source reachability, not proof that runtime execution calls a function. Every route declared in a reaching route module is listed. Boot warnings remain in the JSON explanation and human output, so missing registrations are visible. `warlock explain <WLxxxx>` keeps its static error-code behavior.
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
import { inspectApp, explainFile } from "@warlock.js/core/tooling";
|
|
171
|
+
|
|
172
|
+
const report = await inspectApp({ sections: ["files"] });
|
|
173
|
+
const source = explainFile("src/app/posts/services/list.service.ts", report);
|
|
174
|
+
console.log(source.role, source.exports, source.importedBy);
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
For route/page reachability in code, call `inspectApp({ sections: ["files", "routes", "pages"] })` in an already booted app. `inspect_files` exposes the section through MCP with a case-insensitive `filter` on file, module or role.
|
|
@@ -118,3 +118,7 @@ await server.close();
|
|
|
118
118
|
- The `warlock-check` topic — what `check_run` and `test_run` report.
|
|
119
119
|
- The `warlock-trace` topic — send a request and read its timeline.
|
|
120
120
|
- The `expose-as-mcp-server` topic of @warlock.js/ai-tools — the transport underneath.
|
|
121
|
+
|
|
122
|
+
## Source file graph
|
|
123
|
+
|
|
124
|
+
Call `inspect_files` with `{ "filter": "service" }` for file paths, modules, convention roles, export names, resolved imports and reverse `importedBy` edges. This section scans `src/` without executing source modules; files-only requests skip the lazy app boot. `inspect_app` includes a `files` count. See `npx warlock explain src/app/posts/services/list.service.ts --json` for reaching routes and pages.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: warlock-trace
|
|
3
|
-
description: 'Verify runtime behaviour without a browser: `warlock trace <method> <url> [--body json|@file] [--header k:v] [--json]` sends one request to the running `warlock dev` server and prints what devtools recorded for it — middleware chain with timings, validation result and errors, handler time, queries with N+1 flags, logs, cache operations, captured mails, the response and timings — as a versioned report (`schemaVersion: 1`); `traceRequest()` returns the same object. Triggers: `warlock trace`, `traceRequest`, `TraceReport`, `buildTraceReport`, `x-request-id`, `.warlock/dev-server.json`, `WL8008`, `WL8009`, `WL5004`, `--id-header`; "did validation pass for this request", "which queries does this endpoint run", "is there an N+1 on this route", "what middleware runs on this route", "check the endpoint after my change", "request timeline as JSON". Skip: the devtools dashboard in a browser — the `devtools
|
|
3
|
+
description: 'Verify runtime behaviour without a browser: `warlock trace <method> <url> [--body json|@file] [--header k:v] [--json]` sends one request to the running `warlock dev` server and prints what devtools recorded for it — middleware chain with timings, validation result and errors, handler time, queries with N+1 flags, logs, cache operations, captured mails, the response and timings — as a versioned report (`schemaVersion: 1`); `traceRequest()` returns the same object. Triggers: `warlock trace`, `traceRequest`, `TraceReport`, `buildTraceReport`, `x-request-id`, `.warlock/dev-server.json`, `WL8008`, `WL8009`, `WL5004`, `--id-header`; "did validation pass for this request", "which queries does this endpoint run", "is there an N+1 on this route", "what middleware runs on this route", "check the endpoint after my change", "request timeline as JSON". Skip: the devtools dashboard in a browser — the `warlock-js-devtools` skill; static route facts (guard, rate limit, schemas) — the `warlock-inspect` topic; typecheck/lint/tests — the `warlock-check` topic.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Warlock — `warlock trace`
|
|
@@ -78,4 +78,4 @@ Devtools is checked before anything is sent. With `--json` a failure prints `{ "
|
|
|
78
78
|
|
|
79
79
|
- The `warlock-inspect` topic — the static facts of a route (guard, rate limit, schemas).
|
|
80
80
|
- The `warlock-check` topic — typecheck, lint, tests and conventions in one run.
|
|
81
|
-
- The `devtools
|
|
81
|
+
- The `warlock-js-devtools` skill — the dashboard behind the timeline.
|
|
@@ -337,5 +337,23 @@ Set a unique owner and registry per app instance, then import `processes` from
|
|
|
337
337
|
the generated module and await `processes.spawn({ kind: "worker", command,
|
|
338
338
|
args, labels })`. Consume output and await `handle.exited`. Use handle stops or
|
|
339
339
|
label filters; never stop processes by command or name. `spawnPty()` lazily
|
|
340
|
-
loads separately installed optional peer `node-pty`. The `
|
|
341
|
-
skill
|
|
340
|
+
loads separately installed optional peer `node-pty`. The `warlock-js-process`
|
|
341
|
+
skill contains complete working examples.
|
|
342
|
+
|
|
343
|
+
## Add the shared design system
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
npx warlock add tailwind
|
|
347
|
+
npx warlock add design-system
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
`design-system` refuses before dependency installation when Tailwind is absent
|
|
351
|
+
from `package.json` or `src/web/app.css`. It adds pinned shadcn primitives and
|
|
352
|
+
Mongez controls to `src/web/design-system`, preserving existing source files.
|
|
353
|
+
Use `--no-install` to record dependencies only, or `--dry-run --json` to preview
|
|
354
|
+
files and dependencies without writing. For example, a generated control is
|
|
355
|
+
`import TextInput from "web/design-system/components/text-input";` with
|
|
356
|
+
`<TextInput id="profile-name" name="name" label="Name" />`.
|
|
357
|
+
See Web's `build-accessible-controls` topic for the complete control contract.
|
|
358
|
+
|
|
359
|
+
Built-in `npx warlock add notifications` preloads `config: ["app"]` so generated locale stubs respect `app.localeCodes`, without bootstrap hooks or connectors.
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { ProductionBuilder } from "./production-builder.mjs";
|
|
2
|
-
|
|
3
|
-
//#region ../../packages/core/src/production/build-app-production.ts
|
|
4
|
-
/**
|
|
5
|
-
* Build the application for production
|
|
6
|
-
* Options are loaded from warlock.config.ts
|
|
7
|
-
*/
|
|
8
|
-
async function buildAppProduction() {
|
|
9
|
-
await new ProductionBuilder().build();
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
//#endregion
|
|
13
|
-
export { buildAppProduction };
|
|
14
|
-
//# sourceMappingURL=build-app-production.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"build-app-production.mjs","names":[],"sources":["../../../../../../../../packages/core/src/production/build-app-production.ts"],"sourcesContent":["import { ProductionBuilder } from \"./production-builder\";\n\n/**\n * Build the application for production\n * Options are loaded from warlock.config.ts\n */\nexport async function buildAppProduction() {\n const builder = new ProductionBuilder();\n await builder.build();\n}\n"],"mappings":";;;;;;;AAMA,eAAsB,qBAAqB;CAEzC,MAAM,IADc,kBACR,CAAC,CAAC,MAAM;AACtB"}
|