@warlock.js/core 4.16.0 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/bin/warlock.js +154 -1
- package/esm/application/application.d.mts +65 -1
- package/esm/application/application.d.mts.map +1 -1
- package/esm/application/application.mjs +62 -0
- package/esm/application/application.mjs.map +1 -1
- package/esm/application/index.d.mts +1 -1
- package/esm/cli/cli-commands.manager.mjs +60 -10
- package/esm/cli/cli-commands.manager.mjs.map +1 -1
- package/esm/cli/commands/dev-server.command.mjs +1 -0
- package/esm/cli/commands/dev-server.command.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/handler-signature.check.mjs +40 -0
- package/esm/cli/commands/doctor/checks/handler-signature.check.mjs.map +1 -0
- package/esm/cli/commands/doctor/checks/index.mjs +4 -2
- package/esm/cli/commands/doctor/checks/index.mjs.map +1 -1
- package/esm/commands/cli-command.d.mts +1 -1
- package/esm/commands/cli-command.d.mts.map +1 -1
- package/esm/commands/cli-command.mjs.map +1 -1
- package/esm/commands/types.d.mts +10 -2
- package/esm/commands/types.d.mts.map +1 -1
- package/esm/config/config-handlers.d.mts +1 -2
- package/esm/config/config-handlers.d.mts.map +1 -1
- package/esm/config/config-handlers.mjs +3 -2
- package/esm/config/config-handlers.mjs.map +1 -1
- package/esm/config/locale-configuration.mjs +29 -0
- package/esm/config/locale-configuration.mjs.map +1 -0
- package/esm/connectors/assert-no-reserved-connector-names.d.mts +7 -0
- package/esm/connectors/assert-no-reserved-connector-names.d.mts.map +1 -0
- package/esm/connectors/assert-no-reserved-connector-names.mjs +44 -0
- package/esm/connectors/assert-no-reserved-connector-names.mjs.map +1 -0
- package/esm/connectors/assert-unique-connector-names.d.mts +7 -0
- package/esm/connectors/assert-unique-connector-names.d.mts.map +1 -0
- package/esm/connectors/assert-unique-connector-names.mjs +20 -0
- package/esm/connectors/assert-unique-connector-names.mjs.map +1 -0
- package/esm/connectors/connectors-manager.d.mts +38 -0
- package/esm/connectors/connectors-manager.d.mts.map +1 -1
- package/esm/connectors/connectors-manager.mjs +45 -12
- package/esm/connectors/connectors-manager.mjs.map +1 -1
- package/esm/connectors/describe-server-address.mjs +75 -0
- package/esm/connectors/describe-server-address.mjs.map +1 -0
- package/esm/connectors/http-connector.d.mts.map +1 -1
- package/esm/connectors/http-connector.mjs +6 -3
- package/esm/connectors/http-connector.mjs.map +1 -1
- package/esm/connectors/index.d.mts +4 -1
- package/esm/connectors/index.mjs +4 -1
- package/esm/connectors/register-configured-connectors.d.mts +14 -0
- package/esm/connectors/register-configured-connectors.d.mts.map +1 -0
- package/esm/connectors/register-configured-connectors.mjs +99 -0
- package/esm/connectors/register-configured-connectors.mjs.map +1 -0
- package/esm/connectors/socket-connector.d.mts.map +1 -1
- package/esm/connectors/socket-connector.mjs +4 -1
- package/esm/connectors/socket-connector.mjs.map +1 -1
- package/esm/connectors/types.d.mts +76 -1
- package/esm/connectors/types.d.mts.map +1 -1
- package/esm/connectors/types.mjs.map +1 -1
- package/esm/database/models/database-log/database-log.d.mts +50 -2
- package/esm/database/models/database-log/database-log.d.mts.map +1 -1
- package/esm/database/utils.d.mts +2 -2
- package/esm/database/utils.d.mts.map +1 -1
- package/esm/dev-server/development-server.mjs +1 -0
- package/esm/dev-server/development-server.mjs.map +1 -1
- package/esm/dev-server/layer-executor.mjs +2 -1
- package/esm/dev-server/layer-executor.mjs.map +1 -1
- package/esm/dev-server/read-config-ast.mjs +48 -0
- package/esm/dev-server/read-config-ast.mjs.map +1 -0
- package/esm/dev-server/run-typings-generation.mjs +18 -0
- package/esm/dev-server/run-typings-generation.mjs.map +1 -0
- package/esm/dev-server/type-generator.mjs +30 -39
- package/esm/dev-server/type-generator.mjs.map +1 -1
- package/esm/generations/add-command.action.mjs +169 -1
- package/esm/generations/add-command.action.mjs.map +1 -1
- package/esm/generations/stubs.mjs +93 -1
- package/esm/generations/stubs.mjs.map +1 -1
- package/esm/http/context/request-context.d.mts +14 -3
- package/esm/http/context/request-context.d.mts.map +1 -1
- package/esm/http/context/request-context.mjs +11 -1
- package/esm/http/context/request-context.mjs.map +1 -1
- package/esm/http/context/request-memo.d.mts +21 -0
- package/esm/http/context/request-memo.d.mts.map +1 -0
- package/esm/http/context/request-memo.mjs +48 -0
- package/esm/http/context/request-memo.mjs.map +1 -0
- package/esm/http/database/RequestLog.d.mts +164 -2
- package/esm/http/database/RequestLog.d.mts.map +1 -1
- package/esm/http/index.d.mts +6 -5
- package/esm/http/index.mjs +2 -1
- package/esm/http/middleware/cache-response-middleware.d.mts +2 -2
- package/esm/http/middleware/cache-response-middleware.d.mts.map +1 -1
- package/esm/http/middleware/cache-response-middleware.mjs +1 -1
- package/esm/http/middleware/cache-response-middleware.mjs.map +1 -1
- package/esm/http/middleware/concurrency-limit.middleware.mjs +1 -1
- package/esm/http/middleware/concurrency-limit.middleware.mjs.map +1 -1
- package/esm/http/middleware/idempotency.middleware.mjs +1 -1
- package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
- package/esm/http/middleware/index.d.mts +1 -1
- package/esm/http/middleware/index.mjs +1 -1
- package/esm/http/middleware/inject-request-context.d.mts +1 -8
- package/esm/http/middleware/inject-request-context.d.mts.map +1 -1
- package/esm/http/middleware/inject-request-context.mjs +9 -22
- package/esm/http/middleware/inject-request-context.mjs.map +1 -1
- package/esm/http/middleware/ip-filter.middleware.mjs +1 -1
- package/esm/http/middleware/ip-filter.middleware.mjs.map +1 -1
- package/esm/http/middleware/maintenance.middleware.mjs +1 -1
- package/esm/http/middleware/maintenance.middleware.mjs.map +1 -1
- package/esm/http/middleware/max-body-size.middleware.mjs +1 -1
- package/esm/http/middleware/max-body-size.middleware.mjs.map +1 -1
- package/esm/http/middleware/rate-limit.middleware.mjs +1 -1
- package/esm/http/middleware/rate-limit.middleware.mjs.map +1 -1
- package/esm/http/middleware/utils/idempotency-key.d.mts +0 -14
- package/esm/http/middleware/utils/idempotency-key.d.mts.map +1 -1
- package/esm/http/middleware/utils/idempotency-key.mjs +19 -1
- package/esm/http/middleware/utils/idempotency-key.mjs.map +1 -1
- package/esm/http/request.d.mts +119 -30
- package/esm/http/request.d.mts.map +1 -1
- package/esm/http/request.mjs +98 -25
- package/esm/http/request.mjs.map +1 -1
- package/esm/http/response.mjs +1 -1
- package/esm/http/response.mjs.map +1 -1
- package/esm/http/types.d.mts +36 -1
- package/esm/http/types.d.mts.map +1 -1
- package/esm/http/uploaded-file.d.mts +51 -19
- package/esm/http/uploaded-file.d.mts.map +1 -1
- package/esm/http/uploaded-file.mjs +36 -8
- package/esm/http/uploaded-file.mjs.map +1 -1
- package/esm/index.d.mts +17 -9
- package/esm/index.mjs +10 -4
- package/esm/production/build-contributions.mjs +115 -0
- package/esm/production/build-contributions.mjs.map +1 -0
- package/esm/production/production-builder.mjs +97 -2
- package/esm/production/production-builder.mjs.map +1 -1
- package/esm/production/resolve-build-config.d.mts +25 -0
- package/esm/production/resolve-build-config.d.mts.map +1 -0
- package/esm/production/resolve-build-config.mjs +43 -1
- package/esm/production/resolve-build-config.mjs.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts +1 -1
- package/esm/repositories/adapters/cascade/filter-applicator.mjs +20 -9
- package/esm/repositories/adapters/cascade/filter-applicator.mjs.map +1 -1
- package/esm/restful/restful.d.mts +29 -8
- package/esm/restful/restful.d.mts.map +1 -1
- package/esm/restful/restful.mjs +31 -13
- package/esm/restful/restful.mjs.map +1 -1
- package/esm/router/describe-route-for-log.mjs +29 -0
- package/esm/router/describe-route-for-log.mjs.map +1 -0
- package/esm/router/index.d.mts +3 -1
- package/esm/router/index.mjs +2 -0
- package/esm/router/log-request-lifecycle.mjs +38 -0
- package/esm/router/log-request-lifecycle.mjs.map +1 -0
- package/esm/router/positional-handler-diagnostics.d.mts +90 -0
- package/esm/router/positional-handler-diagnostics.d.mts.map +1 -0
- package/esm/router/positional-handler-diagnostics.mjs +247 -0
- package/esm/router/positional-handler-diagnostics.mjs.map +1 -0
- package/esm/router/route-registry.d.mts +34 -0
- package/esm/router/route-registry.d.mts.map +1 -0
- package/esm/router/router.d.mts.map +1 -1
- package/esm/router/router.mjs +87 -63
- package/esm/router/router.mjs.map +1 -1
- package/esm/router/types.d.mts +23 -5
- package/esm/router/types.d.mts.map +1 -1
- package/esm/storage/storage.d.mts.map +1 -1
- package/esm/storage/storage.mjs +1 -1
- package/esm/storage/storage.mjs.map +1 -1
- package/esm/storage/utils/safe-fetch.d.mts +11 -1
- package/esm/storage/utils/safe-fetch.d.mts.map +1 -1
- package/esm/storage/utils/safe-fetch.mjs +51 -4
- package/esm/storage/utils/safe-fetch.mjs.map +1 -1
- package/esm/tests/vitest-setup.mjs +1 -1
- package/esm/utils/load-environment.mjs +33 -2
- package/esm/utils/load-environment.mjs.map +1 -1
- package/esm/utils/types.d.mts +4 -0
- package/esm/utils/types.d.mts.map +1 -1
- package/esm/validation/validateAll.mjs +4 -1
- package/esm/validation/validateAll.mjs.map +1 -1
- package/esm/validation/validators/file-validator.d.mts +25 -1
- package/esm/validation/validators/file-validator.d.mts.map +1 -1
- package/esm/warlock-config/index.mjs +1 -1
- package/esm/warlock-config/normalize-build-config.mjs.map +1 -1
- package/esm/warlock-config/types.d.mts +36 -2
- package/esm/warlock-config/types.d.mts.map +1 -1
- package/package.json +15 -12
- package/skills/request-memo/SKILL.md +142 -0
- package/skills/use-request-locals/SKILL.md +144 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Route } from "./types.mjs";
|
|
2
|
+
import { log } from "@warlock.js/logger";
|
|
3
|
+
|
|
4
|
+
//#region ../core/src/router/positional-handler-diagnostics.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* One route whose handler looks like it was written for v4.
|
|
7
|
+
*/
|
|
8
|
+
type PositionalHandlerSuspect = {
|
|
9
|
+
/** HTTP method the route was registered under. */method: Route["method"]; /** Full route path, prefixes already applied. */
|
|
10
|
+
path: string; /** Handler function name, or `"(anonymous)"` when it has none. */
|
|
11
|
+
handlerName: string; /** Route file the route came from, when the router knows it. */
|
|
12
|
+
sourceFile: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Does this handler look like it was written for the v4 positional signature?
|
|
16
|
+
*
|
|
17
|
+
* ## The signal, and what it misses
|
|
18
|
+
*
|
|
19
|
+
* `Function.length` alone is not enough, because it stops counting at the first
|
|
20
|
+
* defaulted parameter:
|
|
21
|
+
*
|
|
22
|
+
* | handler | `.length` | actually |
|
|
23
|
+
* | ---------------------------------- | --------- | -------- |
|
|
24
|
+
* | `({ request, response }) => …` | 1 | v5 |
|
|
25
|
+
* | `(ctx) => …` | 1 | v5 |
|
|
26
|
+
* | `(request, response) => …` | 2 | v4 |
|
|
27
|
+
* | `(request, response = x) => …` | 1 | v4 |
|
|
28
|
+
*
|
|
29
|
+
* So the primary signal is the function's own source: a handler is suspect when
|
|
30
|
+
* it declares **two or more** parameters and the first is **not** destructured.
|
|
31
|
+
* Reading the source catches the defaulted row that arity cannot, and rules out
|
|
32
|
+
* the `({ … }, extra)` shape that arity would wrongly flag.
|
|
33
|
+
*
|
|
34
|
+
* When the source is unreadable — a bound or native function — this falls back
|
|
35
|
+
* to `handler.length >= 2`, which `bind` preserves. That is a weaker signal but
|
|
36
|
+
* never a wrong one for the common cases; it only loses the defaulted row.
|
|
37
|
+
*
|
|
38
|
+
* ## What is still missed, by design
|
|
39
|
+
*
|
|
40
|
+
* A one-parameter v4 handler (`(request) => …`) is indistinguishable from a v5
|
|
41
|
+
* `(ctx) => …` and is deliberately not flagged — guessing there would produce
|
|
42
|
+
* false positives on correct code. False positives against the canonical
|
|
43
|
+
* `({ … })` form are essentially nil, and every miss simply leaves today's
|
|
44
|
+
* behaviour in place.
|
|
45
|
+
*/
|
|
46
|
+
declare function looksLikePositionalHandler(handler: unknown): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Inspect one route's handler as it registers, recording it when it looks like
|
|
49
|
+
* the v4 positional form. Called from `Router.add`, so the cost is paid once per
|
|
50
|
+
* route at registration and never per request.
|
|
51
|
+
*
|
|
52
|
+
* Deliberately total: any unexpected failure in the heuristic is swallowed, so a
|
|
53
|
+
* diagnostic can never be the reason a route fails to register.
|
|
54
|
+
*/
|
|
55
|
+
declare function inspectHandlerSignature(handler: unknown, route: {
|
|
56
|
+
method: Route["method"];
|
|
57
|
+
path: string;
|
|
58
|
+
sourceFile: string;
|
|
59
|
+
}): void;
|
|
60
|
+
/**
|
|
61
|
+
* Every suspect recorded so far, in registration order.
|
|
62
|
+
*/
|
|
63
|
+
declare function listPositionalHandlerSuspects(): readonly PositionalHandlerSuspect[];
|
|
64
|
+
/**
|
|
65
|
+
* Drop the suspects belonging to a route file. Kept in step with
|
|
66
|
+
* `Router.removeRoutesBySourceFile` so an HMR reload that fixes a handler does
|
|
67
|
+
* not keep reporting the version it replaced.
|
|
68
|
+
*/
|
|
69
|
+
declare function forgetPositionalHandlerSuspects(sourceFile: string): void;
|
|
70
|
+
/**
|
|
71
|
+
* Drop every recorded suspect. Intended for tests, which share the router
|
|
72
|
+
* singleton.
|
|
73
|
+
*/
|
|
74
|
+
declare function clearPositionalHandlerSuspects(): void;
|
|
75
|
+
/**
|
|
76
|
+
* The one-line diagnostic for a single route. Written for someone who has never
|
|
77
|
+
* read Warlock's internals: it names the handler, the route, what is wrong, and
|
|
78
|
+
* the exact edit that fixes it.
|
|
79
|
+
*/
|
|
80
|
+
declare function describePositionalHandlerSuspect(suspect: PositionalHandlerSuspect): string;
|
|
81
|
+
/**
|
|
82
|
+
* The full boot-time warning: every suspect, once, in one entry.
|
|
83
|
+
*
|
|
84
|
+
* One boot, one list — not one warning per route, and emphatically not one 500
|
|
85
|
+
* per request. Returns the reported suspects so callers can assert on them.
|
|
86
|
+
*/
|
|
87
|
+
declare function reportPositionalHandlerSuspects(logger?: Pick<typeof log, "warn">): PositionalHandlerSuspect[];
|
|
88
|
+
//#endregion
|
|
89
|
+
export { PositionalHandlerSuspect, clearPositionalHandlerSuspects, describePositionalHandlerSuspect, forgetPositionalHandlerSuspects, inspectHandlerSignature, listPositionalHandlerSuspects, looksLikePositionalHandler, reportPositionalHandlerSuspects };
|
|
90
|
+
//# sourceMappingURL=positional-handler-diagnostics.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"positional-handler-diagnostics.d.mts","names":[],"sources":["../../../../../../../core/src/router/positional-handler-diagnostics.ts"],"mappings":";;;;AAyPsE;AAmBtE;;AAnBsE,KArN1D,wBAAA;EAwOsE,kDAtOhF,MAAA,EAAQ,KAAK,YA+OC;EA5Od,IAAA;EAGA,WAAA,UAyOgE;EAtOhE,UAAA;AAAA;;;AAkP4C;AAS9C;;;;AAAkF;AAclF;;;;;;;;;;;;;AAAsF;;;;;;;;;;;iBAhGtE,0BAAA,CAA2B,OAAgB;;;;;;;;;iBA+B3C,uBAAA,CACd,OAAA,WACA,KAAA;EAAS,MAAA,EAAQ,KAAK;EAAY,IAAA;EAAc,UAAA;AAAA;;;;iBAmBlC,6BAAA,aAA0C,wBAAwB;;;;;;iBASlE,+BAAA,CAAgC,UAAkB;;;;;iBAYlD,8BAAA;;;;;;iBASA,gCAAA,CAAiC,OAAiC,EAAxB,wBAAwB;;;;;;;iBAclE,+BAAA,CAAgC,MAAA,GAAQ,IAAA,QAAY,GAAA,YAAkB,wBAAA"}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { log } from "@warlock.js/logger";
|
|
2
|
+
|
|
3
|
+
//#region ../core/src/router/positional-handler-diagnostics.ts
|
|
4
|
+
/**
|
|
5
|
+
* Early detection of route handlers still written against the **v4 positional
|
|
6
|
+
* signature** — `(request, response)` — after v5 moved to a single context
|
|
7
|
+
* object, `({ request, response })`.
|
|
8
|
+
*
|
|
9
|
+
* ## Why this exists
|
|
10
|
+
*
|
|
11
|
+
* A v4 handler is not rejected anywhere. It registers fine, and the router
|
|
12
|
+
* calls it with one argument, so `response` is simply `undefined`. The app only
|
|
13
|
+
* breaks on the first request that reaches it, with:
|
|
14
|
+
*
|
|
15
|
+
* TypeError: Cannot read properties of undefined (reading 'success')
|
|
16
|
+
*
|
|
17
|
+
* That message names nothing the reader can act on — not the route, not the
|
|
18
|
+
* handler, not the change to make. This module turns that late, opaque failure
|
|
19
|
+
* into one explicit list printed at boot, and into a `warlock doctor` check.
|
|
20
|
+
*
|
|
21
|
+
* The break itself is intentional; nothing here restores the positional form.
|
|
22
|
+
* Detection and diagnostics only.
|
|
23
|
+
*
|
|
24
|
+
* ## Why it warns and never throws
|
|
25
|
+
*
|
|
26
|
+
* The signal is a heuristic (see {@link looksLikePositionalHandler}), so a
|
|
27
|
+
* false positive is possible in principle. Turning one into a boot failure
|
|
28
|
+
* would take a working application down over a guess, which is strictly worse
|
|
29
|
+
* than the problem being diagnosed. Everything on this path is therefore a
|
|
30
|
+
* warning: nothing here throws, and nothing here changes how a handler is
|
|
31
|
+
* called. A miss simply degrades to the old runtime `TypeError`.
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Collected across the whole registration pass so the warning can be emitted
|
|
35
|
+
* ONCE, as a single list, rather than one line per route (or — as before — one
|
|
36
|
+
* mystery 500 per request).
|
|
37
|
+
*/
|
|
38
|
+
const suspects = [];
|
|
39
|
+
/**
|
|
40
|
+
* Split the parameter list of a function's source into top-level parameters.
|
|
41
|
+
*
|
|
42
|
+
* Depth-aware and quote-aware, because a default value may itself contain
|
|
43
|
+
* commas, parentheses, braces or strings — `(request, response = f(a, b))` is
|
|
44
|
+
* two parameters, not three. Anything unbalanced returns `undefined`: refusing
|
|
45
|
+
* to guess is what keeps a parse quirk from becoming a false warning.
|
|
46
|
+
*
|
|
47
|
+
* @param openIndex index of the `(` that opens the parameter list.
|
|
48
|
+
*/
|
|
49
|
+
function splitTopLevelParameters(source, openIndex) {
|
|
50
|
+
const parameters = [];
|
|
51
|
+
let depth = 0;
|
|
52
|
+
let current = "";
|
|
53
|
+
let quote = "";
|
|
54
|
+
for (let index = openIndex; index < source.length; index++) {
|
|
55
|
+
const char = source[index];
|
|
56
|
+
if (quote) {
|
|
57
|
+
if (char === "\\") {
|
|
58
|
+
current += char + (source[index + 1] ?? "");
|
|
59
|
+
index++;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (char === quote) quote = "";
|
|
63
|
+
current += char;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (char === "\"" || char === "'" || char === "`") {
|
|
67
|
+
quote = char;
|
|
68
|
+
current += char;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (char === "(" || char === "[" || char === "{") {
|
|
72
|
+
depth++;
|
|
73
|
+
if (depth === 1) continue;
|
|
74
|
+
current += char;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (char === ")" || char === "]" || char === "}") {
|
|
78
|
+
depth--;
|
|
79
|
+
if (depth === 0) {
|
|
80
|
+
if (current.trim()) parameters.push(current.trim());
|
|
81
|
+
return parameters;
|
|
82
|
+
}
|
|
83
|
+
current += char;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (char === "," && depth === 1) {
|
|
87
|
+
parameters.push(current.trim());
|
|
88
|
+
current = "";
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
current += char;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Read a function's declared parameters from its own source.
|
|
96
|
+
*
|
|
97
|
+
* Returns `undefined` whenever the source cannot be trusted, which callers must
|
|
98
|
+
* treat as "no information" rather than "no parameters":
|
|
99
|
+
*
|
|
100
|
+
* - `Function.prototype.bind` replaces the body with `[native code]`, so every
|
|
101
|
+
* `[Controller, "method"]` tuple handler lands here (the router binds them);
|
|
102
|
+
* - native functions likewise;
|
|
103
|
+
* - a class, whose first `(` belongs to a constructor or a method, not to a
|
|
104
|
+
* parameter list;
|
|
105
|
+
* - anything that fails to parse.
|
|
106
|
+
*/
|
|
107
|
+
function readParameterList(handler) {
|
|
108
|
+
let source;
|
|
109
|
+
try {
|
|
110
|
+
source = Function.prototype.toString.call(handler);
|
|
111
|
+
} catch {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (source.includes("[native code]")) return void 0;
|
|
115
|
+
if (/^\s*class[\s{]/.test(source)) return void 0;
|
|
116
|
+
const bareArrow = source.match(/^\s*(?:async\s+)?([A-Za-z_$][\w$]*)\s*=>/);
|
|
117
|
+
if (bareArrow) return [bareArrow[1]];
|
|
118
|
+
const openIndex = source.indexOf("(");
|
|
119
|
+
if (openIndex === -1) return void 0;
|
|
120
|
+
return splitTopLevelParameters(source, openIndex);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Whether a parameter is written as a destructuring pattern — `{ request }` or
|
|
124
|
+
* `[a, b]` — as opposed to a plain name.
|
|
125
|
+
*/
|
|
126
|
+
function isDestructured(parameter) {
|
|
127
|
+
const start = parameter.trimStart();
|
|
128
|
+
return start.startsWith("{") || start.startsWith("[");
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Does this handler look like it was written for the v4 positional signature?
|
|
132
|
+
*
|
|
133
|
+
* ## The signal, and what it misses
|
|
134
|
+
*
|
|
135
|
+
* `Function.length` alone is not enough, because it stops counting at the first
|
|
136
|
+
* defaulted parameter:
|
|
137
|
+
*
|
|
138
|
+
* | handler | `.length` | actually |
|
|
139
|
+
* | ---------------------------------- | --------- | -------- |
|
|
140
|
+
* | `({ request, response }) => …` | 1 | v5 |
|
|
141
|
+
* | `(ctx) => …` | 1 | v5 |
|
|
142
|
+
* | `(request, response) => …` | 2 | v4 |
|
|
143
|
+
* | `(request, response = x) => …` | 1 | v4 |
|
|
144
|
+
*
|
|
145
|
+
* So the primary signal is the function's own source: a handler is suspect when
|
|
146
|
+
* it declares **two or more** parameters and the first is **not** destructured.
|
|
147
|
+
* Reading the source catches the defaulted row that arity cannot, and rules out
|
|
148
|
+
* the `({ … }, extra)` shape that arity would wrongly flag.
|
|
149
|
+
*
|
|
150
|
+
* When the source is unreadable — a bound or native function — this falls back
|
|
151
|
+
* to `handler.length >= 2`, which `bind` preserves. That is a weaker signal but
|
|
152
|
+
* never a wrong one for the common cases; it only loses the defaulted row.
|
|
153
|
+
*
|
|
154
|
+
* ## What is still missed, by design
|
|
155
|
+
*
|
|
156
|
+
* A one-parameter v4 handler (`(request) => …`) is indistinguishable from a v5
|
|
157
|
+
* `(ctx) => …` and is deliberately not flagged — guessing there would produce
|
|
158
|
+
* false positives on correct code. False positives against the canonical
|
|
159
|
+
* `({ … })` form are essentially nil, and every miss simply leaves today's
|
|
160
|
+
* behaviour in place.
|
|
161
|
+
*/
|
|
162
|
+
function looksLikePositionalHandler(handler) {
|
|
163
|
+
if (typeof handler !== "function") return false;
|
|
164
|
+
const parameters = readParameterList(handler);
|
|
165
|
+
if (parameters) return parameters.length >= 2 && !isDestructured(parameters[0]);
|
|
166
|
+
return handler.length >= 2;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* The name to print for a handler.
|
|
170
|
+
*
|
|
171
|
+
* `Function.bind` prefixes the name with `"bound "`, and the router binds every
|
|
172
|
+
* `[Controller, "method"]` tuple handler. The bare method name is what the user
|
|
173
|
+
* actually wrote, so that is what gets printed.
|
|
174
|
+
*/
|
|
175
|
+
function handlerDisplayName(handler) {
|
|
176
|
+
return handler.name?.replace(/^bound /, "").trim() || "(anonymous)";
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Inspect one route's handler as it registers, recording it when it looks like
|
|
180
|
+
* the v4 positional form. Called from `Router.add`, so the cost is paid once per
|
|
181
|
+
* route at registration and never per request.
|
|
182
|
+
*
|
|
183
|
+
* Deliberately total: any unexpected failure in the heuristic is swallowed, so a
|
|
184
|
+
* diagnostic can never be the reason a route fails to register.
|
|
185
|
+
*/
|
|
186
|
+
function inspectHandlerSignature(handler, route) {
|
|
187
|
+
try {
|
|
188
|
+
if (!looksLikePositionalHandler(handler)) return;
|
|
189
|
+
suspects.push({
|
|
190
|
+
method: route.method,
|
|
191
|
+
path: route.path,
|
|
192
|
+
handlerName: handlerDisplayName(handler),
|
|
193
|
+
sourceFile: route.sourceFile
|
|
194
|
+
});
|
|
195
|
+
} catch {}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Every suspect recorded so far, in registration order.
|
|
199
|
+
*/
|
|
200
|
+
function listPositionalHandlerSuspects() {
|
|
201
|
+
return suspects;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Drop the suspects belonging to a route file. Kept in step with
|
|
205
|
+
* `Router.removeRoutesBySourceFile` so an HMR reload that fixes a handler does
|
|
206
|
+
* not keep reporting the version it replaced.
|
|
207
|
+
*/
|
|
208
|
+
function forgetPositionalHandlerSuspects(sourceFile) {
|
|
209
|
+
for (let index = suspects.length - 1; index >= 0; index--) if (suspects[index].sourceFile === sourceFile) suspects.splice(index, 1);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Drop every recorded suspect. Intended for tests, which share the router
|
|
213
|
+
* singleton.
|
|
214
|
+
*/
|
|
215
|
+
function clearPositionalHandlerSuspects() {
|
|
216
|
+
suspects.length = 0;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* The one-line diagnostic for a single route. Written for someone who has never
|
|
220
|
+
* read Warlock's internals: it names the handler, the route, what is wrong, and
|
|
221
|
+
* the exact edit that fixes it.
|
|
222
|
+
*/
|
|
223
|
+
function describePositionalHandlerSuspect(suspect) {
|
|
224
|
+
return `Handler "${suspect.handlerName}" (${suspect.method} ${suspect.path}) looks like the v4 positional signature (request, response). v5 passes a single context object — change it to ({ request, response }).`;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* The full boot-time warning: every suspect, once, in one entry.
|
|
228
|
+
*
|
|
229
|
+
* One boot, one list — not one warning per route, and emphatically not one 500
|
|
230
|
+
* per request. Returns the reported suspects so callers can assert on them.
|
|
231
|
+
*/
|
|
232
|
+
function reportPositionalHandlerSuspects(logger = log) {
|
|
233
|
+
const reported = [...suspects];
|
|
234
|
+
if (reported.length === 0) return reported;
|
|
235
|
+
const headline = reported.length === 1 ? "1 route handler looks like the v4 positional signature." : `${reported.length} route handlers look like the v4 positional signature.`;
|
|
236
|
+
logger.warn({
|
|
237
|
+
module: "router",
|
|
238
|
+
action: "handlerSignature",
|
|
239
|
+
message: `${headline} Warlock v5 calls every route handler with a single context object, so a second parameter is always undefined and the request fails as soon as it is used:\n` + reported.map((suspect) => ` - ${describePositionalHandlerSuspect(suspect)}`).join("\n"),
|
|
240
|
+
context: { handlers: reported }
|
|
241
|
+
});
|
|
242
|
+
return reported;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
//#endregion
|
|
246
|
+
export { clearPositionalHandlerSuspects, describePositionalHandlerSuspect, forgetPositionalHandlerSuspects, inspectHandlerSignature, listPositionalHandlerSuspects, looksLikePositionalHandler, reportPositionalHandlerSuspects };
|
|
247
|
+
//# sourceMappingURL=positional-handler-diagnostics.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"positional-handler-diagnostics.mjs","names":[],"sources":["../../../../../../../core/src/router/positional-handler-diagnostics.ts"],"sourcesContent":["/**\n * Early detection of route handlers still written against the **v4 positional\n * signature** — `(request, response)` — after v5 moved to a single context\n * object, `({ request, response })`.\n *\n * ## Why this exists\n *\n * A v4 handler is not rejected anywhere. It registers fine, and the router\n * calls it with one argument, so `response` is simply `undefined`. The app only\n * breaks on the first request that reaches it, with:\n *\n * TypeError: Cannot read properties of undefined (reading 'success')\n *\n * That message names nothing the reader can act on — not the route, not the\n * handler, not the change to make. This module turns that late, opaque failure\n * into one explicit list printed at boot, and into a `warlock doctor` check.\n *\n * The break itself is intentional; nothing here restores the positional form.\n * Detection and diagnostics only.\n *\n * ## Why it warns and never throws\n *\n * The signal is a heuristic (see {@link looksLikePositionalHandler}), so a\n * false positive is possible in principle. Turning one into a boot failure\n * would take a working application down over a guess, which is strictly worse\n * than the problem being diagnosed. Everything on this path is therefore a\n * warning: nothing here throws, and nothing here changes how a handler is\n * called. A miss simply degrades to the old runtime `TypeError`.\n */\n\nimport { log } from \"@warlock.js/logger\";\nimport type { Route } from \"./types\";\n\n/**\n * One route whose handler looks like it was written for v4.\n */\nexport type PositionalHandlerSuspect = {\n /** HTTP method the route was registered under. */\n method: Route[\"method\"];\n\n /** Full route path, prefixes already applied. */\n path: string;\n\n /** Handler function name, or `\"(anonymous)\"` when it has none. */\n handlerName: string;\n\n /** Route file the route came from, when the router knows it. */\n sourceFile: string;\n};\n\n/**\n * Collected across the whole registration pass so the warning can be emitted\n * ONCE, as a single list, rather than one line per route (or — as before — one\n * mystery 500 per request).\n */\nconst suspects: PositionalHandlerSuspect[] = [];\n\n/**\n * Split the parameter list of a function's source into top-level parameters.\n *\n * Depth-aware and quote-aware, because a default value may itself contain\n * commas, parentheses, braces or strings — `(request, response = f(a, b))` is\n * two parameters, not three. Anything unbalanced returns `undefined`: refusing\n * to guess is what keeps a parse quirk from becoming a false warning.\n *\n * @param openIndex index of the `(` that opens the parameter list.\n */\nfunction splitTopLevelParameters(source: string, openIndex: number): string[] | undefined {\n const parameters: string[] = [];\n\n let depth = 0;\n let current = \"\";\n let quote = \"\";\n\n for (let index = openIndex; index < source.length; index++) {\n const char = source[index];\n\n if (quote) {\n if (char === \"\\\\\") {\n current += char + (source[index + 1] ?? \"\");\n index++;\n continue;\n }\n\n if (char === quote) {\n quote = \"\";\n }\n\n current += char;\n continue;\n }\n\n if (char === '\"' || char === \"'\" || char === \"`\") {\n quote = char;\n current += char;\n continue;\n }\n\n if (char === \"(\" || char === \"[\" || char === \"{\") {\n depth++;\n\n // The paren that opens the list is punctuation, not part of a parameter.\n if (depth === 1) continue;\n\n current += char;\n continue;\n }\n\n if (char === \")\" || char === \"]\" || char === \"}\") {\n depth--;\n\n if (depth === 0) {\n if (current.trim()) {\n parameters.push(current.trim());\n }\n\n return parameters;\n }\n\n current += char;\n continue;\n }\n\n if (char === \",\" && depth === 1) {\n parameters.push(current.trim());\n current = \"\";\n continue;\n }\n\n current += char;\n }\n\n // Never found the closing paren — treat the source as unreadable.\n return undefined;\n}\n\n/**\n * Read a function's declared parameters from its own source.\n *\n * Returns `undefined` whenever the source cannot be trusted, which callers must\n * treat as \"no information\" rather than \"no parameters\":\n *\n * - `Function.prototype.bind` replaces the body with `[native code]`, so every\n * `[Controller, \"method\"]` tuple handler lands here (the router binds them);\n * - native functions likewise;\n * - a class, whose first `(` belongs to a constructor or a method, not to a\n * parameter list;\n * - anything that fails to parse.\n */\nfunction readParameterList(handler: Function): string[] | undefined {\n let source: string;\n\n try {\n source = Function.prototype.toString.call(handler);\n } catch {\n return undefined;\n }\n\n if (source.includes(\"[native code]\")) return undefined;\n\n if (/^\\s*class[\\s{]/.test(source)) return undefined;\n\n // A single parameter needs no parentheses: `ctx => …`, `async ctx => …`.\n const bareArrow = source.match(/^\\s*(?:async\\s+)?([A-Za-z_$][\\w$]*)\\s*=>/);\n\n if (bareArrow) return [bareArrow[1]];\n\n const openIndex = source.indexOf(\"(\");\n\n if (openIndex === -1) return undefined;\n\n return splitTopLevelParameters(source, openIndex);\n}\n\n/**\n * Whether a parameter is written as a destructuring pattern — `{ request }` or\n * `[a, b]` — as opposed to a plain name.\n */\nfunction isDestructured(parameter: string) {\n const start = parameter.trimStart();\n\n return start.startsWith(\"{\") || start.startsWith(\"[\");\n}\n\n/**\n * Does this handler look like it was written for the v4 positional signature?\n *\n * ## The signal, and what it misses\n *\n * `Function.length` alone is not enough, because it stops counting at the first\n * defaulted parameter:\n *\n * | handler | `.length` | actually |\n * | ---------------------------------- | --------- | -------- |\n * | `({ request, response }) => …` | 1 | v5 |\n * | `(ctx) => …` | 1 | v5 |\n * | `(request, response) => …` | 2 | v4 |\n * | `(request, response = x) => …` | 1 | v4 |\n *\n * So the primary signal is the function's own source: a handler is suspect when\n * it declares **two or more** parameters and the first is **not** destructured.\n * Reading the source catches the defaulted row that arity cannot, and rules out\n * the `({ … }, extra)` shape that arity would wrongly flag.\n *\n * When the source is unreadable — a bound or native function — this falls back\n * to `handler.length >= 2`, which `bind` preserves. That is a weaker signal but\n * never a wrong one for the common cases; it only loses the defaulted row.\n *\n * ## What is still missed, by design\n *\n * A one-parameter v4 handler (`(request) => …`) is indistinguishable from a v5\n * `(ctx) => …` and is deliberately not flagged — guessing there would produce\n * false positives on correct code. False positives against the canonical\n * `({ … })` form are essentially nil, and every miss simply leaves today's\n * behaviour in place.\n */\nexport function looksLikePositionalHandler(handler: unknown): boolean {\n if (typeof handler !== \"function\") return false;\n\n const parameters = readParameterList(handler);\n\n if (parameters) {\n return parameters.length >= 2 && !isDestructured(parameters[0]);\n }\n\n return handler.length >= 2;\n}\n\n/**\n * The name to print for a handler.\n *\n * `Function.bind` prefixes the name with `\"bound \"`, and the router binds every\n * `[Controller, \"method\"]` tuple handler. The bare method name is what the user\n * actually wrote, so that is what gets printed.\n */\nfunction handlerDisplayName(handler: Function): string {\n return handler.name?.replace(/^bound /, \"\").trim() || \"(anonymous)\";\n}\n\n/**\n * Inspect one route's handler as it registers, recording it when it looks like\n * the v4 positional form. Called from `Router.add`, so the cost is paid once per\n * route at registration and never per request.\n *\n * Deliberately total: any unexpected failure in the heuristic is swallowed, so a\n * diagnostic can never be the reason a route fails to register.\n */\nexport function inspectHandlerSignature(\n handler: unknown,\n route: { method: Route[\"method\"]; path: string; sourceFile: string },\n) {\n try {\n if (!looksLikePositionalHandler(handler)) return;\n\n suspects.push({\n method: route.method,\n path: route.path,\n handlerName: handlerDisplayName(handler as Function),\n sourceFile: route.sourceFile,\n });\n } catch {\n // A diagnostic must never break registration.\n }\n}\n\n/**\n * Every suspect recorded so far, in registration order.\n */\nexport function listPositionalHandlerSuspects(): readonly PositionalHandlerSuspect[] {\n return suspects;\n}\n\n/**\n * Drop the suspects belonging to a route file. Kept in step with\n * `Router.removeRoutesBySourceFile` so an HMR reload that fixes a handler does\n * not keep reporting the version it replaced.\n */\nexport function forgetPositionalHandlerSuspects(sourceFile: string) {\n for (let index = suspects.length - 1; index >= 0; index--) {\n if (suspects[index].sourceFile === sourceFile) {\n suspects.splice(index, 1);\n }\n }\n}\n\n/**\n * Drop every recorded suspect. Intended for tests, which share the router\n * singleton.\n */\nexport function clearPositionalHandlerSuspects() {\n suspects.length = 0;\n}\n\n/**\n * The one-line diagnostic for a single route. Written for someone who has never\n * read Warlock's internals: it names the handler, the route, what is wrong, and\n * the exact edit that fixes it.\n */\nexport function describePositionalHandlerSuspect(suspect: PositionalHandlerSuspect): string {\n return (\n `Handler \"${suspect.handlerName}\" (${suspect.method} ${suspect.path}) looks like ` +\n `the v4 positional signature (request, response). ` +\n `v5 passes a single context object — change it to ({ request, response }).`\n );\n}\n\n/**\n * The full boot-time warning: every suspect, once, in one entry.\n *\n * One boot, one list — not one warning per route, and emphatically not one 500\n * per request. Returns the reported suspects so callers can assert on them.\n */\nexport function reportPositionalHandlerSuspects(logger: Pick<typeof log, \"warn\"> = log) {\n const reported = [...suspects];\n\n if (reported.length === 0) return reported;\n\n const headline =\n reported.length === 1\n ? \"1 route handler looks like the v4 positional signature.\"\n : `${reported.length} route handlers look like the v4 positional signature.`;\n\n logger.warn({\n module: \"router\",\n action: \"handlerSignature\",\n message:\n `${headline} Warlock v5 calls every route handler with a single context object, ` +\n `so a second parameter is always undefined and the request fails as soon as it is used:\\n` +\n reported.map((suspect) => ` - ${describePositionalHandlerSuspect(suspect)}`).join(\"\\n\"),\n context: { handlers: reported },\n });\n\n return reported;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Route } from "./types.mjs";
|
|
2
|
+
|
|
3
|
+
//#region ../core/src/router/route-registry.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Route Registry
|
|
6
|
+
* Manages dynamic route matching using find-my-way for HMR support
|
|
7
|
+
*/
|
|
8
|
+
declare class RouteRegistry {
|
|
9
|
+
private router;
|
|
10
|
+
constructor();
|
|
11
|
+
/**
|
|
12
|
+
* Register all routes from the router's internal list
|
|
13
|
+
*/
|
|
14
|
+
register(routes: Route[]): void;
|
|
15
|
+
/**
|
|
16
|
+
* Register a single route
|
|
17
|
+
*/
|
|
18
|
+
registerRoute(route: Route): void;
|
|
19
|
+
/**
|
|
20
|
+
* Find a matching route for the given method and URL
|
|
21
|
+
* @returns Matched route with extracted params, or null if no match
|
|
22
|
+
*/
|
|
23
|
+
find(method: string, url: string): {
|
|
24
|
+
route: Route;
|
|
25
|
+
params: Record<string, string>;
|
|
26
|
+
} | null;
|
|
27
|
+
/**
|
|
28
|
+
* Get all registered routes count (for debugging)
|
|
29
|
+
*/
|
|
30
|
+
getRouteCount(): number;
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { RouteRegistry };
|
|
34
|
+
//# sourceMappingURL=route-registry.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-registry.d.mts","names":[],"sources":["../../../../../../../core/src/router/route-registry.ts"],"mappings":";;;;;AAsBA;;cAAa,aAAA;EAAA,QACH,MAAA;;EA6CI;;;EAjCL,QAAA,CAAS,MAAA,EAAQ,KAAA;EAZhB;;;EA+BD,aAAA,CAAc,KAAA,EAAO,KAAA;EAnBZ;;;;EA8BT,IAAA,CACL,MAAA,UACA,GAAA;IACG,KAAA,EAAO,KAAA;IAAO,MAAA,EAAQ,MAAA;EAAA;EAAf;;;EAkBL,aAAA;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.mts","names":[],"sources":["../../../../../../../core/src/router/router.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"router.d.mts","names":[],"sources":["../../../../../../../core/src/router/router.ts"],"mappings":"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"}
|