carrick 0.3.106 → 0.3.108
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/dist/hook/refresh.js +8 -1
- package/dist/hook/refresh.js.map +1 -1
- package/package.json +6 -6
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/sidecar/dist/src/capture/anchors.d.ts +15 -2
- package/sidecar/dist/src/capture/anchors.js +28 -11
- package/sidecar/dist/src/capture/api.d.ts +15 -0
- package/sidecar/dist/src/capture/check-classify.d.ts +9 -0
- package/sidecar/dist/src/capture/check-classify.js +20 -0
- package/sidecar/dist/src/capture/check-fields.d.ts +24 -0
- package/sidecar/dist/src/capture/check-fields.js +54 -36
- package/sidecar/dist/src/capture/check-poison.js +4 -14
- package/sidecar/dist/src/capture/check-union.d.ts +40 -0
- package/sidecar/dist/src/capture/check-union.js +92 -0
- package/sidecar/dist/src/capture/check.js +5 -0
- package/sidecar/dist/src/capture/index.js +138 -80
- package/sidecar/dist/src/capture/installed-package.d.ts +2 -0
- package/sidecar/dist/src/capture/installed-package.js +2 -1
- package/sidecar/dist/src/capture/outside-root.d.ts +19 -0
- package/sidecar/dist/src/capture/outside-root.js +39 -2
- package/sidecar/dist/src/capture/self-check.js +3 -13
- package/sidecar/dist/src/capture/specifiers.d.ts +14 -0
- package/sidecar/dist/src/capture/specifiers.js +25 -0
- package/sidecar/dist/src/definition-resolver.d.ts +5 -8
- package/sidecar/dist/src/definition-resolver.js +5 -7
- package/sidecar/dist/src/function-line-index.d.ts +30 -0
- package/sidecar/dist/src/function-line-index.js +162 -0
- package/sidecar/dist/src/index.d.ts +5 -0
- package/sidecar/dist/src/index.js +62 -9
- package/sidecar/dist/src/infer-timing.d.ts +54 -0
- package/sidecar/dist/src/infer-timing.js +124 -0
- package/sidecar/dist/src/line-index.d.ts +9 -0
- package/sidecar/dist/src/line-index.js +26 -0
- package/sidecar/dist/src/progress.d.ts +22 -0
- package/sidecar/dist/src/progress.js +31 -0
- package/sidecar/dist/src/retype.d.ts +4 -2
- package/sidecar/dist/src/retype.js +10 -23
- package/sidecar/dist/src/type-inferrer.d.ts +238 -12
- package/sidecar/dist/src/type-inferrer.js +772 -168
- package/sidecar/dist/src/types.d.ts +83 -6
- package/sidecar/dist/src/validators.d.ts +54 -16
- package/sidecar/dist/src/validators.js +4 -0
- package/templates/skills/carrick-reuse.md +6 -5
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
*/
|
|
27
27
|
import { Node, SyntaxKind, ts } from 'ts-morph';
|
|
28
28
|
import { readsResponseStatus, statusesIn, SUCCEEDED, testsOnPath, } from './failure-path.js';
|
|
29
|
+
import { lineIndex } from './line-index.js';
|
|
29
30
|
import { fileDiagnostics } from './unwidened.js';
|
|
30
31
|
/** Names appended to a file that is not ours carry this prefix. */
|
|
31
32
|
const PREFIX = '__carrick_';
|
|
@@ -52,9 +53,11 @@ export class Retyper {
|
|
|
52
53
|
* Judge every item, spending at most `budgetMs`. Each item rebuilds the
|
|
53
54
|
* program at least twice, so a consumer with many calls could otherwise
|
|
54
55
|
* outrun the caller's read deadline and lose every answer; the items the
|
|
55
|
-
* budget does not reach abstain and say so.
|
|
56
|
+
* budget does not reach abstain and say so. `onJudged` is called after each
|
|
57
|
+
* item the budget reached, so the caller can report progress while the
|
|
58
|
+
* event loop is blocked (carrick#1945).
|
|
56
59
|
*/
|
|
57
|
-
run(items, budgetMs) {
|
|
60
|
+
run(items, budgetMs, onJudged) {
|
|
58
61
|
const deadline = performance.now() + budgetMs;
|
|
59
62
|
// What each file said before any rewrite. Every rewrite is undone, so it
|
|
60
63
|
// is the same for every item in the file.
|
|
@@ -63,12 +66,15 @@ export class Retyper {
|
|
|
63
66
|
if (performance.now() >= deadline) {
|
|
64
67
|
return abstain(item, `the retype check ran out of its ${budgetMs}ms budget`);
|
|
65
68
|
}
|
|
69
|
+
let outcome;
|
|
66
70
|
try {
|
|
67
|
-
|
|
71
|
+
outcome = this.runOne(item, before);
|
|
68
72
|
}
|
|
69
73
|
catch (err) {
|
|
70
|
-
|
|
74
|
+
outcome = abstain(item, `the retype check failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
71
75
|
}
|
|
76
|
+
onJudged?.();
|
|
77
|
+
return outcome;
|
|
72
78
|
});
|
|
73
79
|
}
|
|
74
80
|
runOne(item, before) {
|
|
@@ -842,22 +848,3 @@ function mapBack(pos, edits) {
|
|
|
842
848
|
}
|
|
843
849
|
return { kind: 'original', pos: pos - shift };
|
|
844
850
|
}
|
|
845
|
-
/** 1-based line of an original-file position. */
|
|
846
|
-
function lineIndex(text) {
|
|
847
|
-
const starts = [0];
|
|
848
|
-
for (let i = 0; i < text.length; i++)
|
|
849
|
-
if (text[i] === '\n')
|
|
850
|
-
starts.push(i + 1);
|
|
851
|
-
return (pos) => {
|
|
852
|
-
let lo = 0;
|
|
853
|
-
let hi = starts.length - 1;
|
|
854
|
-
while (lo < hi) {
|
|
855
|
-
const mid = (lo + hi + 1) >> 1;
|
|
856
|
-
if (starts[mid] <= pos)
|
|
857
|
-
lo = mid;
|
|
858
|
-
else
|
|
859
|
-
hi = mid - 1;
|
|
860
|
-
}
|
|
861
|
-
return lo + 1;
|
|
862
|
-
};
|
|
863
|
-
}
|
|
@@ -63,6 +63,11 @@ export interface TypeInferrerOptions {
|
|
|
63
63
|
*/
|
|
64
64
|
unwidenedBudgetMs?: number;
|
|
65
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Called each time an `infer` batch is done with one of its requests,
|
|
68
|
+
* whatever that request answered: skipped, refused, failed or inferred.
|
|
69
|
+
*/
|
|
70
|
+
export type InferRequestDone = () => void;
|
|
66
71
|
/**
|
|
67
72
|
* TypeInferrer - Extracts types from source code, both explicit and inferred
|
|
68
73
|
*
|
|
@@ -81,6 +86,12 @@ export declare class TypeInferrer {
|
|
|
81
86
|
*/
|
|
82
87
|
private readonly readNodes;
|
|
83
88
|
private readonly unwidenedBudgetMs;
|
|
89
|
+
/**
|
|
90
|
+
* The files a request has named to this inferrer, as the requests named
|
|
91
|
+
* them (carrick#1985). It lives as long as the project does, so the first
|
|
92
|
+
* request of a file is the first of the process, not of a batch.
|
|
93
|
+
*/
|
|
94
|
+
private readonly filesAsked;
|
|
84
95
|
constructor(options: TypeInferrerOptions);
|
|
85
96
|
/**
|
|
86
97
|
* What the structural printer needs to tell the user's own declarations from
|
|
@@ -94,9 +105,10 @@ export declare class TypeInferrer {
|
|
|
94
105
|
*
|
|
95
106
|
* @param requests - Array of inference requests
|
|
96
107
|
* @param extractionConfig - Agent-generated extraction config for payload unwrapping
|
|
108
|
+
* @param onRequestDone - Called once per request, as the batch is done with it
|
|
97
109
|
* @returns InferResult with inferred types or errors
|
|
98
110
|
*/
|
|
99
|
-
infer(requests: InferRequestItem[], extractionConfig?: ExtractionConfig): InferResult;
|
|
111
|
+
infer(requests: InferRequestItem[], extractionConfig?: ExtractionConfig, onRequestDone?: InferRequestDone): InferResult;
|
|
100
112
|
/**
|
|
101
113
|
* carrick#1836: list on `result` the declarations behind the names its text
|
|
102
114
|
* prints that the request's file cannot resolve (`PrintedTypes.namesIn`).
|
|
@@ -187,6 +199,61 @@ export declare class TypeInferrer {
|
|
|
187
199
|
*/
|
|
188
200
|
private resolveParamTarget;
|
|
189
201
|
private inferResponseBody;
|
|
202
|
+
/**
|
|
203
|
+
* The handler a module exports on `line`: a function that opens on exactly
|
|
204
|
+
* that line, exported at the top of its module, where no call on the line
|
|
205
|
+
* registers a route (carrick#807).
|
|
206
|
+
*
|
|
207
|
+
* That is the anchor of a route its module's place in the project states:
|
|
208
|
+
* the row's line is the handler's own export, and the module's exports are
|
|
209
|
+
* how the framework finds it. Each condition keeps another kind of row out:
|
|
210
|
+
*
|
|
211
|
+
* - the line has to be the function's first, with no tolerance. A model
|
|
212
|
+
* row that names no site of its own can sit on any line of a handler,
|
|
213
|
+
* and the nearest function to such a line is whatever is declared
|
|
214
|
+
* beside it;
|
|
215
|
+
* - a method of a class is a controller's handler, whose rows are
|
|
216
|
+
* anchored on what a model located before the method's own return;
|
|
217
|
+
* - a line that registers a route has a registration to read.
|
|
218
|
+
*/
|
|
219
|
+
private handlerDeclaredAtLine;
|
|
220
|
+
/**
|
|
221
|
+
* `handlerDeclaredAtLine` without its registration test, for a caller that
|
|
222
|
+
* has already looked for a registration on the line.
|
|
223
|
+
*/
|
|
224
|
+
private exportedFunctionOpeningOn;
|
|
225
|
+
/**
|
|
226
|
+
* The response of a handler the request's line declares, for a request
|
|
227
|
+
* that also located an expression inside it (carrick#807).
|
|
228
|
+
*
|
|
229
|
+
* The handler's own return is read first, exactly as a `function_return`
|
|
230
|
+
* request at the line reads it, and that reading stands: a body it
|
|
231
|
+
* recovered, and a decision it made not to publish one. The located
|
|
232
|
+
* expression is consulted in one case only. Where the handler returns a
|
|
233
|
+
* call nothing resolves (its library is not installed), the return walk
|
|
234
|
+
* reads no argument the source does not annotate, because it cannot tell a
|
|
235
|
+
* response sender from a query. A located payload that is an ARGUMENT of
|
|
236
|
+
* such a returned call says which it is, so the same walk runs again with
|
|
237
|
+
* that callee taken as a sender: every success body the handler returns
|
|
238
|
+
* through it, error branches dropped as before. The located expression's
|
|
239
|
+
* own type is never what is published here.
|
|
240
|
+
*
|
|
241
|
+
* Returns `undefined` when the located expression is something the return
|
|
242
|
+
* walk never looked at, so it is left to the readings below:
|
|
243
|
+
* - the handler returns nothing (`void`): it sends through a parameter;
|
|
244
|
+
* - the handler returns transport the walk read no body out of, and the
|
|
245
|
+
* located expression is not part of what it returns. A body built before
|
|
246
|
+
* the response is returned (`const res = send(body); ...; return res`)
|
|
247
|
+
* is one. Named on a send that states an error or redirect status, it is
|
|
248
|
+
* no success body and the row abstains.
|
|
249
|
+
*/
|
|
250
|
+
private responseOfDeclaredHandler;
|
|
251
|
+
/**
|
|
252
|
+
* The call inside one of `returned` that the located expression is, or is
|
|
253
|
+
* an argument of: the send a located payload was handed to. `undefined`
|
|
254
|
+
* when the located expression is not part of what the handler returns.
|
|
255
|
+
*/
|
|
256
|
+
private returnedSendHolding;
|
|
190
257
|
/**
|
|
191
258
|
* True when a located call's own result is the route's payload, so the
|
|
192
259
|
* transitional drill into its first argument must not run (carrick#1732).
|
|
@@ -291,6 +358,14 @@ export declare class TypeInferrer {
|
|
|
291
358
|
* else, and is not reported.
|
|
292
359
|
*/
|
|
293
360
|
private statedBodyAtRead;
|
|
361
|
+
/**
|
|
362
|
+
* The type node `statedBodyAtRead` reads, for a caller that wants the
|
|
363
|
+
* annotation itself: a consumer's response read reports its root, and a
|
|
364
|
+
* handler's request read prints it (carrick#807). One reading of "stated at
|
|
365
|
+
* the read" for both, so the two cannot disagree about which annotation
|
|
366
|
+
* belongs to a read.
|
|
367
|
+
*/
|
|
368
|
+
private typeNodeStatedAtRead;
|
|
294
369
|
/**
|
|
295
370
|
* A stated type with `any` or `unknown` written anywhere in it (`unknown`,
|
|
296
371
|
* `Record<string, unknown>`, `{ items: any[] }`) leaves a position open: it
|
|
@@ -350,12 +425,54 @@ export declare class TypeInferrer {
|
|
|
350
425
|
*/
|
|
351
426
|
private resultCarrierPayload;
|
|
352
427
|
/**
|
|
353
|
-
*
|
|
354
|
-
*
|
|
355
|
-
*
|
|
356
|
-
|
|
428
|
+
* The shape test of `resultCarrierPayload`: the carrier `type` is, once a
|
|
429
|
+
* promise-like around it is peeled, and the type arguments a branch of it
|
|
430
|
+
* holds as a member. `undefined` when `type` is not a carrier.
|
|
431
|
+
*/
|
|
432
|
+
private resultCarrierArguments;
|
|
433
|
+
/**
|
|
434
|
+
* The decided abstain of a call whose result carries transport the
|
|
435
|
+
* service's wrapper rules verify and read no payload out of (carrick#1841,
|
|
436
|
+
* carrick#1843): `unknown` with `machinery_envelope` at the root and no
|
|
437
|
+
* anchor. The root reason is what keeps the capture's own locator from
|
|
438
|
+
* re-reading the raw call (`inference_decided_no_contract`,
|
|
439
|
+
* engine/type_compat_v2.rs).
|
|
440
|
+
*/
|
|
441
|
+
private transportAbstain;
|
|
442
|
+
/**
|
|
443
|
+
* `Future<T>` -> `T` for a thenable, read off the await protocol rather
|
|
444
|
+
* than a name: a `then` whose first parameter is a callback, whose own
|
|
445
|
+
* first parameter is the value awaiting it yields. `Promise` and
|
|
446
|
+
* `PromiseLike` are peeled by `unwrapPromiseType` before this.
|
|
447
|
+
*
|
|
448
|
+
* The callback is read through `null` and `undefined` (carrick#1877). A
|
|
449
|
+
* `then` of the source's own making declares `(value: T) => void`; the
|
|
450
|
+
* platform's declares `onfulfilled?: ((value: T) => ...) | null`, and that
|
|
451
|
+
* is the `then` a subclass of `Promise` inherits. Read as written, an
|
|
452
|
+
* optional, nullable callback has no call signature, and the subclass was
|
|
453
|
+
* not seen as a thenable at all.
|
|
454
|
+
*
|
|
455
|
+
* A `then` that cannot be called, or whose first parameter is no callback,
|
|
456
|
+
* is no protocol, and the type is returned as it is.
|
|
457
|
+
*
|
|
458
|
+
* The compiler's own awaited type arbitrates. This walk reads the first
|
|
459
|
+
* signature of `then`; the language reads all of them. Where awaiting the
|
|
460
|
+
* type and awaiting what this walk found are not the same thing to the
|
|
461
|
+
* compiler (an overloaded `then` whose first signature is not the one
|
|
462
|
+
* `await` takes), the walk did not read the protocol, and the type is
|
|
463
|
+
* returned as it is rather than published as a guess.
|
|
357
464
|
*/
|
|
358
465
|
private unwrapThenableType;
|
|
466
|
+
/** The value `then`'s first signature hands its callback, read until it stops changing. */
|
|
467
|
+
private firstThenValue;
|
|
468
|
+
/**
|
|
469
|
+
* What `await` yields for `type` where the names do not say: `type` is,
|
|
470
|
+
* once `Promise` and `PromiseLike` are peeled, a thenable by the protocol
|
|
471
|
+
* (a subclass of `Promise`, a class with a `then` of its own). `undefined`
|
|
472
|
+
* where the names say it all or `type` is no thenable, so a caller keeps
|
|
473
|
+
* the reading it had (carrick#1877).
|
|
474
|
+
*/
|
|
475
|
+
private awaitedBeyondPromise;
|
|
359
476
|
/**
|
|
360
477
|
* The platform's error shape, in full: `name` and `message` strings AND a
|
|
361
478
|
* `stack`, which is what the `Error` interface declares and every subclass
|
|
@@ -456,7 +573,17 @@ export declare class TypeInferrer {
|
|
|
456
573
|
*/
|
|
457
574
|
private castsOfUnreadParameter;
|
|
458
575
|
/**
|
|
459
|
-
* The zero-argument whole-body read
|
|
576
|
+
* The zero-argument whole-body read taken in place on the value `callExpr`
|
|
577
|
+
* yields, or `undefined` (carrick#1851): `(await fetch(url)).text()`. The
|
|
578
|
+
* receiver is the call itself, through the wrappers that leave a value as
|
|
579
|
+
* it is (parentheses, `await`, `!`), so it is the same read
|
|
580
|
+
* `bodyReadOnReceiver` finds on a binding of that value. A call that is not
|
|
581
|
+
* awaited first is read the same way: a request that is a promise and reads
|
|
582
|
+
* its own body (`send(url).json()`) yields the body from that read too.
|
|
583
|
+
*/
|
|
584
|
+
private bodyReadOnCallValue;
|
|
585
|
+
/**
|
|
586
|
+
* The zero-argument whole-body read that takes `receiver` as its receiver,
|
|
460
587
|
* `res.json()` or `res.text()`, or `undefined`. A text read is a body read
|
|
461
588
|
* like a json one (carrick#1842): without it, `return res.text()` left the
|
|
462
589
|
* walk on the response binding and published the transport object.
|
|
@@ -518,12 +645,27 @@ export declare class TypeInferrer {
|
|
|
518
645
|
* Try to unwrap a type using a single ExtractionRule.
|
|
519
646
|
*/
|
|
520
647
|
private tryUnwrapWithRule;
|
|
648
|
+
/**
|
|
649
|
+
* The names `type` goes by, own symbol first (carrick#1843).
|
|
650
|
+
*
|
|
651
|
+
* `type Task<A> = __Task<A>` has the class's symbol and arguments, and the
|
|
652
|
+
* alias's beside them. `type Reply<T> = { ... }` has the anonymous `__type`
|
|
653
|
+
* with no arguments of its own. `type Outcome<A, E> = Done<A, E> |
|
|
654
|
+
* Failed<A, E>` has no symbol of its own at all. In each, the alias and its
|
|
655
|
+
* arguments are what a rule naming `Task`, `Reply` or `Outcome` describes.
|
|
656
|
+
*/
|
|
657
|
+
private wrapperReadings;
|
|
521
658
|
/**
|
|
522
659
|
* Extract the payload type from a matched wrapper. Returns null when the
|
|
523
660
|
* rule matched the wrapper but no payload is recoverable from generics or
|
|
524
661
|
* property paths — the caller decides what a payload-less match means
|
|
525
662
|
* (verified machinery collapses to `unknown` after every rule has run;
|
|
526
663
|
* a name-only match leaves the type untouched).
|
|
664
|
+
*
|
|
665
|
+
* `payloadGenericIndex` counts the arguments of `reading`, the name the
|
|
666
|
+
* rule matched (carrick#1843): an alias is free to order its parameters
|
|
667
|
+
* differently from the type it stands for, so the same index into the
|
|
668
|
+
* other list is a different argument.
|
|
527
669
|
*/
|
|
528
670
|
private extractPayloadFromWrapper;
|
|
529
671
|
/**
|
|
@@ -819,9 +961,22 @@ export declare class TypeInferrer {
|
|
|
819
961
|
*
|
|
820
962
|
* Under `statedOnly` the annotation is the ONLY thing that counts, so an
|
|
821
963
|
* unresolvable callee's arguments never become a contract by accident.
|
|
964
|
+
*
|
|
965
|
+
* `asSent` judges the object in the form it is sent in, which is what an
|
|
966
|
+
* ARGUMENT handed to a sender is asked; see `typeIsObjectShaped`.
|
|
822
967
|
*/
|
|
823
968
|
private nodeCarriesPayloadContract;
|
|
824
|
-
/**
|
|
969
|
+
/**
|
|
970
|
+
* Object, array-of-object, or a union/intersection containing one.
|
|
971
|
+
*
|
|
972
|
+
* With `asSent` the object is judged in the form it is SENT in
|
|
973
|
+
* (carrick#1163): a value that declares `toJSON()` travels as what that
|
|
974
|
+
* returns. A `URL` or a `Date` is therefore the string it serialises to,
|
|
975
|
+
* the bare primitive this rule already refuses, and `redirect(new URL(path,
|
|
976
|
+
* base))` hands over a location exactly as `redirect("/next")` does
|
|
977
|
+
* (carrick#807). A value whose JSON form is itself an object is a body like
|
|
978
|
+
* any other.
|
|
979
|
+
*/
|
|
825
980
|
private typeIsObjectShaped;
|
|
826
981
|
/**
|
|
827
982
|
* The `satisfies X` / `as X` / `<X>` annotation node on an expression, when
|
|
@@ -920,11 +1075,19 @@ export declare class TypeInferrer {
|
|
|
920
1075
|
/**
|
|
921
1076
|
* Declaration file (absolute path) of the anchor symbol
|
|
922
1077
|
* `primaryTypeSymbol` reports for this type, or `undefined` when the type
|
|
923
|
-
* has no user-facing anchor or no source declaration.
|
|
924
|
-
*
|
|
925
|
-
*
|
|
926
|
-
*
|
|
927
|
-
*
|
|
1078
|
+
* has no user-facing anchor or no source declaration. Every path that
|
|
1079
|
+
* reports the symbol reports this beside it (carrick#1819): it is where a
|
|
1080
|
+
* reader finds the type an anchor names. The scanner's pub/sub two-anchor
|
|
1081
|
+
* arbitration (carrick#413) also uses it to re-aim a demoted explicit
|
|
1082
|
+
* bundle request: the bundler resolves a `SymbolRequest` only against
|
|
1083
|
+
* declarations IN its `source_file`, so the request must point at the file
|
|
1084
|
+
* that actually declares the tsc-witnessed payload type.
|
|
1085
|
+
*
|
|
1086
|
+
* The declarations read are those of the type's own symbol, so a name
|
|
1087
|
+
* imported through a barrel reports the file that declares it, and a name
|
|
1088
|
+
* two files declare reports the one this type resolves to. A declaration in
|
|
1089
|
+
* an installed package or a TypeScript lib is reported as it is found, as
|
|
1090
|
+
* an absolute path; what a reader is shown for it is the scanner's call.
|
|
928
1091
|
*
|
|
929
1092
|
* Only declaration kinds the bundler's `validateSymbols` can resolve
|
|
930
1093
|
* (interface, type alias, class, enum, function, variable) count. A
|
|
@@ -1194,6 +1357,46 @@ export declare class TypeInferrer {
|
|
|
1194
1357
|
* Returns null (not a spurious type) for a genuinely payload-less handler.
|
|
1195
1358
|
*/
|
|
1196
1359
|
private inferRequestReadFromHandler;
|
|
1360
|
+
/**
|
|
1361
|
+
* The call in a handler that reads the request's body off the platform
|
|
1362
|
+
* request the handler was handed, or `undefined` (carrick#807).
|
|
1363
|
+
*
|
|
1364
|
+
* Read by shape, with no method name consulted:
|
|
1365
|
+
*
|
|
1366
|
+
* - a call that takes nothing, on a member of a value whose type is request
|
|
1367
|
+
* machinery (`typeIsFrameworkMachinery`: declared by the platform or an
|
|
1368
|
+
* installed library, and carrying its body readers);
|
|
1369
|
+
* - that value is rooted at one of the handler's OWN parameters, named or
|
|
1370
|
+
* destructured. A response read off an outbound call inside the handler
|
|
1371
|
+
* (`(await upstream.json()) as Rate`) has the same shape one variable
|
|
1372
|
+
* away, and is the opposite side of a different exchange;
|
|
1373
|
+
* - and the call's result, awaited, is `any` or `unknown`: the platform's
|
|
1374
|
+
* untyped parse. A read that states its own type (`formData()`, a typed
|
|
1375
|
+
* `json<T>()`) is not this shape and is left to the readers that
|
|
1376
|
+
* already handle it.
|
|
1377
|
+
*
|
|
1378
|
+
* The first such call in source order: a body is read once.
|
|
1379
|
+
*/
|
|
1380
|
+
private platformBodyReadIn;
|
|
1381
|
+
/**
|
|
1382
|
+
* The request contract the source states AT a body read, or null when it
|
|
1383
|
+
* states none there (carrick#807).
|
|
1384
|
+
*
|
|
1385
|
+
* Three statements count, each of them on the read itself:
|
|
1386
|
+
*
|
|
1387
|
+
* - a cast on it: `(await request.json()) as NewWidget`;
|
|
1388
|
+
* - the annotation of the binding it initialises:
|
|
1389
|
+
* `const input: NewWidget = await request.json()`;
|
|
1390
|
+
* - a schema the read, or the binding that holds it, is handed to
|
|
1391
|
+
* (`schemaConsumingRead`): the schema's input is what a caller may send.
|
|
1392
|
+
*
|
|
1393
|
+
* The first two are `typeNodeStatedAtRead`, the reading a consumer's
|
|
1394
|
+
* response read already gets. An annotation further out is not one of them:
|
|
1395
|
+
* `const saved: Saved = await save(await request.json())` types what `save`
|
|
1396
|
+
* returned, and reading it as the body would publish the wrong side of the
|
|
1397
|
+
* handler. Nor is a placeholder (`as unknown`, `Record<string, unknown>`).
|
|
1398
|
+
*/
|
|
1399
|
+
private requestStatedAtBodyRead;
|
|
1197
1400
|
/**
|
|
1198
1401
|
* Resolve a type-annotation/type-argument node to fully-structural text,
|
|
1199
1402
|
* dropping any `Promise<…>` wrapper (`c.req.json<T>()` returns `Promise<T>`,
|
|
@@ -1337,8 +1540,31 @@ export declare class TypeInferrer {
|
|
|
1337
1540
|
* request type resolves `body` to `unknown`/`any`, which the useless-type
|
|
1338
1541
|
* guard rejects. So a handler that declares nothing yields null and the next
|
|
1339
1542
|
* anchor runs.
|
|
1543
|
+
*
|
|
1544
|
+
* The member has to be one the route's own annotation can have filled
|
|
1545
|
+
* (carrick#807). The platform `Request` declares `body` too, as the byte
|
|
1546
|
+
* stream every request carries, and so does each library type that extends
|
|
1547
|
+
* it. That is concrete, so it passed the useless-type guard and a handler
|
|
1548
|
+
* taking the platform request published a stream as its request contract,
|
|
1549
|
+
* ahead of the body read inside it. A `body` a library declares with one
|
|
1550
|
+
* fixed type says nothing about this route and is skipped.
|
|
1340
1551
|
*/
|
|
1341
1552
|
private requestBodyFromHandlerParams;
|
|
1553
|
+
/**
|
|
1554
|
+
* True when a member is declared by a library, or by the platform, with a
|
|
1555
|
+
* type that names none of its declaring type's parameters: the same type on
|
|
1556
|
+
* every value, whichever route the value belongs to.
|
|
1557
|
+
*
|
|
1558
|
+
* `body: ReqBody` on a request type generic in its body is a slot, and the
|
|
1559
|
+
* handler's annotation fills it. `readonly body: ReadableStream<Uint8Array>
|
|
1560
|
+
* | null` on the platform request is not. A member the repo declares itself
|
|
1561
|
+
* is never fixed in this sense: writing `body: NewWidget` on the handler's
|
|
1562
|
+
* own request type is the annotation, and one declaration of the repo's
|
|
1563
|
+
* among several (an intersection with the platform type) decides it. A
|
|
1564
|
+
* declaration that states no type at all is left to the guards that read
|
|
1565
|
+
* the type.
|
|
1566
|
+
*/
|
|
1567
|
+
private memberIsFixedByItsLibrary;
|
|
1342
1568
|
/**
|
|
1343
1569
|
* Anchor (b2): the contract declared by a VALIDATOR MIDDLEWARE on the
|
|
1344
1570
|
* registration (carrick#964).
|