carrick 0.3.101 → 0.3.103

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.
Files changed (39) hide show
  1. package/package.json +6 -6
  2. package/plugin/.claude-plugin/plugin.json +1 -1
  3. package/sidecar/dist/src/bundler.d.ts +3 -92
  4. package/sidecar/dist/src/bundler.js +5 -265
  5. package/sidecar/dist/src/capture/anchors.js +113 -8
  6. package/sidecar/dist/src/capture/check-fields.js +19 -5
  7. package/sidecar/dist/src/capture/check-probe.d.ts +5 -0
  8. package/sidecar/dist/src/capture/check-probe.js +31 -2
  9. package/sidecar/dist/src/capture/check-workspace.d.ts +3 -0
  10. package/sidecar/dist/src/capture/check-workspace.js +13 -16
  11. package/sidecar/dist/src/capture/check.js +5 -5
  12. package/sidecar/dist/src/capture/deep-walk.js +45 -12
  13. package/sidecar/dist/src/capture/deno-project.d.ts +2 -1
  14. package/sidecar/dist/src/capture/deno-project.js +22 -18
  15. package/sidecar/dist/src/capture/guarded-fs.d.ts +76 -0
  16. package/sidecar/dist/src/capture/guarded-fs.js +182 -0
  17. package/sidecar/dist/src/capture/index.js +60 -26
  18. package/sidecar/dist/src/capture/outside-root.d.ts +41 -0
  19. package/sidecar/dist/src/capture/outside-root.js +101 -0
  20. package/sidecar/dist/src/capture/paths-rewrite.d.ts +8 -0
  21. package/sidecar/dist/src/capture/paths-rewrite.js +9 -7
  22. package/sidecar/dist/src/capture/repair-dangling.d.ts +11 -1
  23. package/sidecar/dist/src/capture/repair-dangling.js +15 -4
  24. package/sidecar/dist/src/capture/self-check.d.ts +3 -0
  25. package/sidecar/dist/src/capture/self-check.js +3 -3
  26. package/sidecar/dist/src/index.d.ts +1 -1
  27. package/sidecar/dist/src/index.js +2 -115
  28. package/sidecar/dist/src/origin.d.ts +49 -8
  29. package/sidecar/dist/src/origin.js +81 -8
  30. package/sidecar/dist/src/project-loader.js +15 -5
  31. package/sidecar/dist/src/type-inferrer.d.ts +72 -0
  32. package/sidecar/dist/src/type-inferrer.js +248 -8
  33. package/sidecar/dist/src/type-structural-expander.d.ts +5 -1
  34. package/sidecar/dist/src/type-structural-expander.js +1 -1
  35. package/sidecar/dist/src/types.d.ts +31 -178
  36. package/sidecar/dist/src/validators.d.ts +58 -914
  37. package/sidecar/dist/src/validators.js +0 -55
  38. package/sidecar/dist/src/monorepo-builder.d.ts +0 -129
  39. package/sidecar/dist/src/monorepo-builder.js +0 -584
@@ -20,7 +20,7 @@
20
20
  import * as path from 'node:path';
21
21
  import { Node, SyntaxKind, ts, } from 'ts-morph';
22
22
  import { validateInferRequestItem } from './validators.js';
23
- import { isExternalOrigin } from './origin.js';
23
+ import { externalImportsOf, isExternalOrigin } from './origin.js';
24
24
  import { addedDiagnostics, applyInsertions, fileDiagnostics, literalInsertions, mapBack, mapForward, normalise, pathOf, } from './unwidened.js';
25
25
  import { expandTypeStructural, } from './type-structural-expander.js';
26
26
  /**
@@ -277,6 +277,7 @@ export class TypeInferrer {
277
277
  return {
278
278
  program: this.project.getProgram().compilerObject,
279
279
  repoRoot: this.repoRoot,
280
+ imports: externalImportsOf(this.project),
280
281
  };
281
282
  }
282
283
  /**
@@ -940,7 +941,9 @@ export class TypeInferrer {
940
941
  this.log(`Span resolves to a callback-registration call at ${request.file_path}:${request.line_number}; no payload to infer`);
941
942
  return null;
942
943
  }
943
- if (args.length > 0) {
944
+ // A call whose result is a value the repo shapes is not a send: it is
945
+ // the payload (carrick#1732), and drilling would publish its input.
946
+ if (args.length > 0 && !this.callResultIsPayload(node)) {
944
947
  payloadNode = args[0];
945
948
  }
946
949
  }
@@ -973,6 +976,31 @@ export class TypeInferrer {
973
976
  const anchor = this.unwrapArrayLevels(this.unwrapPromiseType(payloadType));
974
977
  return this.createInferredType(request, typeString, false, this.getNodeLocation(payloadNode), unwrapResult.wasUnwrapped ? unwrapResult.typeString : undefined, this.primaryTypeSymbol(anchor.element), anchor.depth);
975
978
  }
979
+ /**
980
+ * True when a located call's own result is the route's payload, so the
981
+ * transitional drill into its first argument must not run (carrick#1732).
982
+ *
983
+ * `res.json(users)` reached that drill because nothing above it recognised
984
+ * the send: its result reads `void`, `any` or `unknown`, and the payload is
985
+ * the argument. `toPublicView(row)` is the opposite case: a mapper building
986
+ * the object the route sends. Its first argument is the row it was built
987
+ * FROM, which carries columns the route never sends.
988
+ *
989
+ * The call's result decides, not where its callee is declared. It is the
990
+ * payload when it reads as one by the rule a response helper's argument is
991
+ * read with (`nodeCarriesPayloadContract`: object-shaped, not machinery,
992
+ * not `void`/`any`/`unknown`) and the object is not a library's own: a
993
+ * codec's writer from `encode(message)` or a reply builder from a send is
994
+ * the library describing itself, and keeps the drill. A library call that
995
+ * returns the repo's own type (`toInstance(View, plain)`) is the payload.
996
+ */
997
+ callResultIsPayload(call) {
998
+ const { element } = this.unwrapArrayLevels(this.unwrapPromiseType(call.getType()));
999
+ if (this.symbolIsLibOrExternalOrigin(element.getSymbol() ?? element.getAliasSymbol())) {
1000
+ return false;
1001
+ }
1002
+ return this.nodeCarriesPayloadContract(call, false);
1003
+ }
976
1004
  /**
977
1005
  * The wire representation a request's printed type takes. A route response
978
1006
  * is serialised as JSON by every sender this layer reads a payload out of,
@@ -1309,7 +1337,132 @@ export class TypeInferrer {
1309
1337
  }
1310
1338
  }
1311
1339
  }
1312
- return this.createInferredType(request, typeString, isExplicit, this.getNodeLocation(terminalNode), unwrapResult.wasUnwrapped ? unwrapResult.typeString : undefined, anchor ? this.primaryTypeSymbol(anchor.element) : undefined, anchor?.depth);
1340
+ const inferred = this.createInferredType(request, typeString, isExplicit, this.getNodeLocation(terminalNode), unwrapResult.wasUnwrapped ? unwrapResult.typeString : undefined, anchor ? this.primaryTypeSymbol(anchor.element) : undefined, anchor?.depth);
1341
+ // carrick#1749: say when the text is the source's own statement of the
1342
+ // body, and what that statement is rooted at, so the scanner can tell a
1343
+ // model symbol that names the body from one that names a part of it.
1344
+ const statedBody = explicitType ? this.statedBodyAtRead(terminalNode) : undefined;
1345
+ if (statedBody) {
1346
+ inferred.stated_body = statedBody;
1347
+ }
1348
+ return inferred;
1349
+ }
1350
+ /**
1351
+ * What the source states the body read at `terminal` to be, when the type
1352
+ * `extractExplicitTypeFromAncestor` printed for it is stated AT the read
1353
+ * (carrick#1749): the read is the operand of that cast, or the initializer
1354
+ * of that annotated declaration, through wrappers that leave a value as it
1355
+ * is (parentheses, `await`, `!`, another cast). An annotation further out —
1356
+ * the declared type of the function the read sits in — describes something
1357
+ * else, and is not reported.
1358
+ */
1359
+ statedBodyAtRead(terminal) {
1360
+ const typeNode = this.explicitTypeNodeFromAncestor(terminal);
1361
+ const owner = typeNode?.getParent();
1362
+ if (!typeNode || !owner || this.leavesAPositionOpen(typeNode))
1363
+ return undefined;
1364
+ let current = terminal;
1365
+ for (;;) {
1366
+ if (current === owner)
1367
+ break;
1368
+ const parent = current.getParent();
1369
+ if (!parent)
1370
+ return undefined;
1371
+ if (parent === owner &&
1372
+ Node.isVariableDeclaration(parent) &&
1373
+ parent.getInitializer() === current) {
1374
+ break;
1375
+ }
1376
+ if (!Node.isParenthesizedExpression(parent) &&
1377
+ !Node.isAwaitExpression(parent) &&
1378
+ !Node.isNonNullExpression(parent) &&
1379
+ !Node.isAsExpression(parent) &&
1380
+ !Node.isTypeAssertion(parent) &&
1381
+ !Node.isSatisfiesExpression(parent)) {
1382
+ return undefined;
1383
+ }
1384
+ current = parent;
1385
+ }
1386
+ return this.statedRoot(typeNode);
1387
+ }
1388
+ /**
1389
+ * A stated type with `any` or `unknown` written anywhere in it (`unknown`,
1390
+ * `Record<string, unknown>`, `{ items: any[] }`) leaves a position open: it
1391
+ * is a placeholder the source narrows later (`const data: unknown = await
1392
+ * res.json()`, then `data as Entry[]`), not its statement of the body.
1393
+ */
1394
+ leavesAPositionOpen(typeNode) {
1395
+ const open = (node) => node.getKind() === SyntaxKind.AnyKeyword || node.getKind() === SyntaxKind.UnknownKeyword;
1396
+ return open(typeNode) || typeNode.getDescendants().some(open);
1397
+ }
1398
+ /**
1399
+ * The named root of a stated body type: `Promise<...>` and `PromiseLike`
1400
+ * (the language's await protocol), array levels, parentheses, `readonly`
1401
+ * and `| null`/`| undefined` are peeled, and what is left is either a type
1402
+ * reference, whose name is the root, or anything else, which has none.
1403
+ */
1404
+ statedRoot(typeNode) {
1405
+ let node = typeNode;
1406
+ let depth = 0;
1407
+ for (let step = 0; step < 16; step++) {
1408
+ if (Node.isParenthesizedTypeNode(node)) {
1409
+ node = node.getTypeNode();
1410
+ continue;
1411
+ }
1412
+ if (Node.isArrayTypeNode(node)) {
1413
+ node = node.getElementTypeNode();
1414
+ depth++;
1415
+ continue;
1416
+ }
1417
+ if (Node.isTypeOperatorTypeNode(node) &&
1418
+ node.getOperator() === SyntaxKind.ReadonlyKeyword) {
1419
+ node = node.getTypeNode();
1420
+ continue;
1421
+ }
1422
+ if (Node.isUnionTypeNode(node)) {
1423
+ const present = node
1424
+ .getTypeNodes()
1425
+ .filter((member) => !((Node.isLiteralTypeNode(member) &&
1426
+ member.getLiteral().getKind() === SyntaxKind.NullKeyword) ||
1427
+ member.getKind() === SyntaxKind.UndefinedKeyword ||
1428
+ member.getKind() === SyntaxKind.NullKeyword));
1429
+ if (present.length === 1) {
1430
+ node = present[0];
1431
+ continue;
1432
+ }
1433
+ break;
1434
+ }
1435
+ if (Node.isTypeReference(node)) {
1436
+ const name = node.getTypeName().getText();
1437
+ const args = node.getTypeArguments();
1438
+ if (args.length === 1 && (name === 'Promise' || name === 'PromiseLike')) {
1439
+ node = args[0];
1440
+ continue;
1441
+ }
1442
+ if (args.length === 1 && (name === 'Array' || name === 'ReadonlyArray')) {
1443
+ node = args[0];
1444
+ depth++;
1445
+ continue;
1446
+ }
1447
+ }
1448
+ break;
1449
+ }
1450
+ const depthField = depth > 0 ? { array_depth: depth } : {};
1451
+ if (!Node.isTypeReference(node)) {
1452
+ return depthField;
1453
+ }
1454
+ const typeName = node.getTypeName();
1455
+ const nameNode = Node.isQualifiedName(typeName) ? typeName.getRight() : typeName;
1456
+ let symbol = nameNode.getSymbol();
1457
+ if (symbol?.isAlias()) {
1458
+ symbol = symbol.getAliasedSymbol() ?? symbol;
1459
+ }
1460
+ const source = symbol?.getDeclarations()[0]?.getSourceFile().getFilePath();
1461
+ return {
1462
+ root: nameNode.getText(),
1463
+ ...(source ? { root_source: source } : {}),
1464
+ ...depthField,
1465
+ };
1313
1466
  }
1314
1467
  inferVariable(sourceFile, request, extractionConfig) {
1315
1468
  const node = this.resolveTargetNode(sourceFile, request);
@@ -1632,6 +1785,14 @@ export class TypeInferrer {
1632
1785
  // Call Result Resolution
1633
1786
  // ===========================================================================
1634
1787
  resolveCallResultTerminalNode(callExpr, func) {
1788
+ // carrick#1749: the call starts a chain, and a callback in it is handed
1789
+ // the body unread and casts it. That cast is the body read, and it comes
1790
+ // before the return-statement answer below, which for a chain is the
1791
+ // value the caller computed from the body, not the body.
1792
+ const chainRead = this.bodyReadInCallbackChain(callExpr);
1793
+ if (chainRead) {
1794
+ return { terminal: chainRead, projectionOnly: false, projections: [] };
1795
+ }
1635
1796
  const returnStmt = callExpr.getFirstAncestorByKind(SyntaxKind.ReturnStatement);
1636
1797
  if (returnStmt) {
1637
1798
  const returnExpr = returnStmt.getExpression();
@@ -2094,6 +2255,80 @@ export class TypeInferrer {
2094
2255
  * HTTP response is read exactly this way whatever produced the response, so
2095
2256
  * the shape is structural, not a framework's name.
2096
2257
  */
2258
+ /**
2259
+ * The body read inside a chain that starts at `callExpr` (carrick#1749):
2260
+ * `request(url).check(ok).mapOk(response => { const data = response as
2261
+ * SearchResponse; ... })`.
2262
+ *
2263
+ * The chain is the run of member calls whose receiver is the call, then
2264
+ * that call's result, and so on. A callback passed to one of them whose
2265
+ * first parameter the compiler types `unknown` is handed a value nothing
2266
+ * has typed yet, which is what a parsed body is; where the source casts
2267
+ * that parameter, the cast is what the caller says the body is. The value
2268
+ * the chain ends in is what the caller computed from it, and publishing
2269
+ * that as the body is the false mismatch this rule exists for.
2270
+ *
2271
+ * Exactly one such cast across the whole chain answers. None, or more than
2272
+ * one (a callback on the failure side can be handed an `unknown` too), and
2273
+ * the walk carries on as before. A parameter typed `any` is not read: an
2274
+ * unresolved library types every callback that way, success and failure
2275
+ * alike, so it says nothing about which one is the body.
2276
+ */
2277
+ bodyReadInCallbackChain(callExpr) {
2278
+ const reads = [];
2279
+ let receiver = callExpr;
2280
+ for (let link = 0; link < 64; link++) {
2281
+ const access = receiver.getParent();
2282
+ if (!access ||
2283
+ !Node.isPropertyAccessExpression(access) ||
2284
+ access.getExpression() !== receiver) {
2285
+ break;
2286
+ }
2287
+ const call = access.getParent();
2288
+ if (!call || !Node.isCallExpression(call) || call.getExpression() !== access) {
2289
+ break;
2290
+ }
2291
+ for (const arg of call.getArguments()) {
2292
+ if (Node.isArrowFunction(arg) || Node.isFunctionExpression(arg)) {
2293
+ reads.push(...this.castsOfUnreadParameter(arg));
2294
+ }
2295
+ }
2296
+ receiver = call;
2297
+ }
2298
+ return reads.length === 1 ? reads[0] : undefined;
2299
+ }
2300
+ /**
2301
+ * The casts of a callback's first parameter, when the compiler types that
2302
+ * parameter `unknown`: `response as T` and `<T>response`, the operand being
2303
+ * the parameter itself. A cast that leaves a position open states nothing
2304
+ * about the body and is skipped.
2305
+ */
2306
+ castsOfUnreadParameter(callback) {
2307
+ const param = callback.getParameters()[0];
2308
+ const name = param?.getNameNode();
2309
+ if (!param || !name || !Node.isIdentifier(name) || !param.getType().isUnknown()) {
2310
+ return [];
2311
+ }
2312
+ const symbol = name.getSymbol();
2313
+ if (!symbol)
2314
+ return [];
2315
+ return callback.getDescendants().filter((node) => {
2316
+ if (!Node.isAsExpression(node) && !Node.isTypeAssertion(node))
2317
+ return false;
2318
+ let operand = node.getExpression();
2319
+ while (Node.isParenthesizedExpression(operand)) {
2320
+ operand = operand.getExpression();
2321
+ }
2322
+ if (!Node.isIdentifier(operand) || operand.getSymbol() !== symbol)
2323
+ return false;
2324
+ const stated = node.getType();
2325
+ const statedNode = node.getTypeNode();
2326
+ return (!!statedNode &&
2327
+ !stated.isAny() &&
2328
+ !stated.isUnknown() &&
2329
+ !this.leavesAPositionOpen(statedNode));
2330
+ });
2331
+ }
2097
2332
  bodyReadOnReceiver(identifier) {
2098
2333
  const access = identifier.getParent();
2099
2334
  if (!access ||
@@ -2610,7 +2845,7 @@ export class TypeInferrer {
2610
2845
  }
2611
2846
  const program = this.project.getProgram().compilerObject;
2612
2847
  for (const decl of symbol.getDeclarations()) {
2613
- if (isExternalOrigin(program, decl.getSourceFile().compilerNode, this.repoRoot)) {
2848
+ if (isExternalOrigin(program, decl.getSourceFile().compilerNode, this.repoRoot, externalImportsOf(this.project))) {
2614
2849
  return true;
2615
2850
  }
2616
2851
  }
@@ -2796,11 +3031,16 @@ export class TypeInferrer {
2796
3031
  return this.unwrapExpressionNode(args[0]);
2797
3032
  }
2798
3033
  extractExplicitTypeFromAncestor(node) {
3034
+ const typeNode = this.explicitTypeNodeFromAncestor(node);
3035
+ return typeNode ? this.expandAnnotationTypeNode(typeNode) : null;
3036
+ }
3037
+ /** The annotation `extractExplicitTypeFromAncestor` prints, as a node. */
3038
+ explicitTypeNodeFromAncestor(node) {
2799
3039
  const varDecl = node.getFirstAncestorByKind(SyntaxKind.VariableDeclaration);
2800
3040
  if (varDecl) {
2801
3041
  const typeNode = varDecl.getTypeNode();
2802
3042
  if (typeNode) {
2803
- return this.expandAnnotationTypeNode(typeNode);
3043
+ return typeNode;
2804
3044
  }
2805
3045
  }
2806
3046
  // Consider the node ITSELF as well as its ancestors: the `call_result`
@@ -2813,7 +3053,7 @@ export class TypeInferrer {
2813
3053
  if (asExpr) {
2814
3054
  const typeNode = asExpr.getTypeNode();
2815
3055
  if (typeNode) {
2816
- return this.expandAnnotationTypeNode(typeNode);
3056
+ return typeNode;
2817
3057
  }
2818
3058
  }
2819
3059
  const typeAssertion = Node.isTypeAssertion(node)
@@ -2822,10 +3062,10 @@ export class TypeInferrer {
2822
3062
  if (typeAssertion) {
2823
3063
  const typeNode = typeAssertion.getTypeNode();
2824
3064
  if (typeNode) {
2825
- return this.expandAnnotationTypeNode(typeNode);
3065
+ return typeNode;
2826
3066
  }
2827
3067
  }
2828
- return null;
3068
+ return undefined;
2829
3069
  }
2830
3070
  /**
2831
3071
  * Render an explicit annotation (`as T`, `<T>`, or a typed binding) as
@@ -29,6 +29,7 @@
29
29
  * structural form rather than a dangling name.
30
30
  */
31
31
  import { type Node, type Type, ts } from 'ts-morph';
32
+ import { type ExternalImports } from './origin.js';
32
33
  /**
33
34
  * Bound on the structural-expansion recursion. Deep enough for every realistic
34
35
  * request/response shape; a backstop against pathological/recursive types the
@@ -83,11 +84,14 @@ export type WireFormat = 'declared' | 'json';
83
84
  * its own cache leaves no such segment in the path (carrick#1264). The program
84
85
  * carries the resolver's own verdict, so it is what `isExternalOrigin` is
85
86
  * asked — the same instrument the inference path uses, so the two layers
86
- * cannot disagree about which types to inline.
87
+ * cannot disagree about which types to inline. `imports` is that verdict kept
88
+ * past the program rebuilds that drop it (carrick#1731), for a project the
89
+ * loader built.
87
90
  */
88
91
  export interface ExpandOrigin {
89
92
  readonly program: ts.Program;
90
93
  readonly repoRoot: string;
94
+ readonly imports?: ExternalImports;
91
95
  }
92
96
  /** Everything `expandTypeStructural` takes besides the type and its origin. */
93
97
  export interface ExpandOptions {
@@ -366,7 +366,7 @@ function isLibraryType(type, origin) {
366
366
  const decls = symbol.getDeclarations();
367
367
  if (decls.length === 0)
368
368
  return false;
369
- return decls.some((decl) => isExternalOrigin(origin.program, decl.getSourceFile().compilerNode, origin.repoRoot));
369
+ return decls.some((decl) => isExternalOrigin(origin.program, decl.getSourceFile().compilerNode, origin.repoRoot, origin.imports));
370
370
  }
371
371
  /**
372
372
  * Non-expanded text for a type. Passes `undefined` as the enclosing node so
@@ -97,21 +97,6 @@ export interface TsconfigSnapshot {
97
97
  [key: string]: unknown;
98
98
  };
99
99
  }
100
- /**
101
- * Metadata for a single repository in the synthetic monorepo.
102
- */
103
- export interface RepoMetadata {
104
- /** Unique name for this repo (used in @carrick/{repoName}/...) */
105
- repoName: string;
106
- /** Pinned dependency versions for this repo */
107
- dependencies: PinnedDependencySnapshot;
108
- /** Closed tsconfig snapshot for this repo */
109
- tsconfig: TsconfigSnapshot;
110
- /** Extraction config for unwrapping machinery types */
111
- extractionConfig?: ExtractionConfig;
112
- /** The emitted surface .d.ts content (after Task 2) */
113
- surfaceContent?: string;
114
- }
115
100
  /**
116
101
  * Base fields present in all requests
117
102
  */
@@ -132,36 +117,11 @@ export interface InitRequest extends BaseRequest {
132
117
  }
133
118
  /**
134
119
  * Request to bundle explicit types from source files
135
- * @deprecated Use emit_surface instead for the new architecture
136
120
  */
137
121
  export interface BundleRequest extends BaseRequest {
138
122
  action: 'bundle';
139
123
  symbols: SymbolRequest[];
140
124
  }
141
- /**
142
- * Request to emit a surface .d.ts file with rewritten module specifiers
143
- */
144
- export interface EmitSurfaceRequest extends BaseRequest {
145
- action: 'emit_surface';
146
- /** The repo name for specifier rewriting (@carrick/{repoName}/...) */
147
- repo_name: string;
148
- /** Payload types to include in the surface */
149
- payloads: PayloadDefinition[];
150
- /** Output path for the surface .d.ts file */
151
- output_path: string;
152
- }
153
- /**
154
- * Definition of a payload type to emit
155
- */
156
- export interface PayloadDefinition {
157
- /** Alias/name for this payload in the surface */
158
- alias: string;
159
- /** The type string (already unwrapped from machinery) */
160
- type_string: string;
161
- /** Optional source information */
162
- source_file?: string;
163
- source_location?: SourceLocation;
164
- }
165
125
  /**
166
126
  * Request to run the v2 "tsc as serializer" capture for one service.
167
127
  * Produces a types-only stub package (compiler-emitted declaration tree +
@@ -223,40 +183,6 @@ export interface InferRequest extends BaseRequest {
223
183
  /** Agent-generated extraction config for machinery unwrapping */
224
184
  extraction_config?: ExtractionConfig;
225
185
  }
226
- /**
227
- * Request to build the synthetic monorepo workspace
228
- */
229
- export interface BuildWorkspaceRequest extends BaseRequest {
230
- action: 'build_workspace';
231
- repos: RepoMetadata[];
232
- /** Root directory for the workspace (defaults to .carrick/workspace) */
233
- workspace_root?: string;
234
- }
235
- /**
236
- * Request to run type compatibility checks
237
- */
238
- export interface CheckCompatibilityRequest extends BaseRequest {
239
- action: 'check_compatibility';
240
- /** Path to the workspace root */
241
- workspace_root: string;
242
- /** Pairs of types to check for compatibility */
243
- checks: CompatibilityCheck[];
244
- }
245
- /**
246
- * A single compatibility check between two types
247
- */
248
- export interface CompatibilityCheck {
249
- /** Source repo name */
250
- source_repo: string;
251
- /** Source payload alias */
252
- source_alias: string;
253
- /** Target repo name */
254
- target_repo: string;
255
- /** Target payload alias */
256
- target_alias: string;
257
- /** Direction: 'source_extends_target' or 'target_extends_source' or 'bidirectional' */
258
- direction: 'source_extends_target' | 'target_extends_source' | 'bidirectional';
259
- }
260
186
  /**
261
187
  * Health check request
262
188
  */
@@ -524,7 +450,7 @@ export interface ListLibrarySurfaceRequest extends BaseRequest {
524
450
  /**
525
451
  * Union type for all possible sidecar requests
526
452
  */
527
- export type SidecarRequest = RetypeCheckRequest | VerifyClientSemanticsRequest | VerifyLibraryClaimsRequest | ListLibrarySurfaceRequest | InitRequest | BundleRequest | EmitSurfaceRequest | CaptureV2Request | CheckV2Request | InferRequest | BuildWorkspaceRequest | CheckCompatibilityRequest | ResolveDefinitionsRequest | HealthRequest | ShutdownRequest;
453
+ export type SidecarRequest = RetypeCheckRequest | VerifyClientSemanticsRequest | VerifyLibraryClaimsRequest | ListLibrarySurfaceRequest | InitRequest | BundleRequest | CaptureV2Request | CheckV2Request | InferRequest | ResolveDefinitionsRequest | HealthRequest | ShutdownRequest;
528
454
  /**
529
455
  * Request for a specific symbol to be bundled
530
456
  */
@@ -588,7 +514,6 @@ export interface InitResponse extends BaseResponse {
588
514
  }
589
515
  /**
590
516
  * Response for bundle action
591
- * @deprecated Use EmitSurfaceResponse instead
592
517
  */
593
518
  export interface BundleResponse extends BaseResponse {
594
519
  /** The bundled .d.ts content */
@@ -600,27 +525,6 @@ export interface BundleResponse extends BaseResponse {
600
525
  /** General errors */
601
526
  errors?: string[];
602
527
  }
603
- /**
604
- * Response for emit_surface action
605
- */
606
- export interface EmitSurfaceResponse extends BaseResponse {
607
- /** Path to the emitted surface file */
608
- output_path?: string;
609
- /** The emitted .d.ts content */
610
- surface_content?: string;
611
- /** Manifest of emitted payloads */
612
- manifest?: SurfaceManifestEntry[];
613
- /** Errors during emission */
614
- errors?: string[];
615
- }
616
- /**
617
- * Entry in the surface manifest
618
- */
619
- export interface SurfaceManifestEntry {
620
- alias: string;
621
- type_string: string;
622
- rewritten_imports: string[];
623
- }
624
528
  /**
625
529
  * Response for infer action
626
530
  */
@@ -630,42 +534,6 @@ export interface InferResponse extends BaseResponse {
630
534
  /** General errors */
631
535
  errors?: string[];
632
536
  }
633
- /**
634
- * Response for build_workspace action
635
- */
636
- export interface BuildWorkspaceResponse extends BaseResponse {
637
- /** Path to the created workspace */
638
- workspace_path?: string;
639
- /** Paths to generated stub packages */
640
- stub_packages?: string[];
641
- /** Path to the checker package */
642
- checker_path?: string;
643
- /** Errors during workspace creation */
644
- errors?: string[];
645
- }
646
- /**
647
- * Response for check_compatibility action
648
- */
649
- export interface CheckCompatibilityResponse extends BaseResponse {
650
- /** Results of each compatibility check */
651
- results?: CompatibilityResult[];
652
- /** TypeScript compiler diagnostics */
653
- diagnostics?: string[];
654
- /** Errors during checking */
655
- errors?: string[];
656
- }
657
- /**
658
- * Result of a single compatibility check
659
- */
660
- export interface CompatibilityResult {
661
- source_repo: string;
662
- source_alias: string;
663
- target_repo: string;
664
- target_alias: string;
665
- compatible: boolean;
666
- /** Diagnostic message if not compatible */
667
- diagnostic?: string;
668
- }
669
537
  /**
670
538
  * Response for resolve_definitions action
671
539
  */
@@ -838,7 +706,7 @@ export interface ListLibrarySurfaceResponse extends BaseResponse {
838
706
  /**
839
707
  * Union type for all possible sidecar responses
840
708
  */
841
- export type SidecarResponse = RetypeCheckResponse | VerifyClientSemanticsResponse | VerifyLibraryClaimsResponse | ListLibrarySurfaceResponse | InitResponse | BundleResponse | EmitSurfaceResponse | CaptureV2Response | CheckV2Response | InferResponse | BuildWorkspaceResponse | CheckCompatibilityResponse | ResolveDefinitionsResponse | HealthResponse | ShutdownResponse | ErrorResponse;
709
+ export type SidecarResponse = RetypeCheckResponse | VerifyClientSemanticsResponse | VerifyLibraryClaimsResponse | ListLibrarySurfaceResponse | InitResponse | BundleResponse | CaptureV2Response | CheckV2Response | InferResponse | ResolveDefinitionsResponse | HealthResponse | ShutdownResponse | ErrorResponse;
842
710
  /**
843
711
  * An entry in the type manifest
844
712
  */
@@ -938,6 +806,35 @@ export interface InferredType {
938
806
  * was dropped as unsound.
939
807
  */
940
808
  unwidened_type_string?: string;
809
+ /**
810
+ * carrick#1749, `call_result` only: present when the source itself states
811
+ * the type of the body it reads, AT the read: a cast of the read
812
+ * (`res.json() as Promise<T>`, a callback's `value as T`) or the annotated
813
+ * declaration it initializes (`const data: T = await res.json()`). The
814
+ * text in `type_string` is then that statement. Absent when no type is
815
+ * stated, or when the only annotation is further away than the read.
816
+ */
817
+ stated_body?: StatedBody;
818
+ }
819
+ /**
820
+ * What the source states a body read to be (carrick#1749). The scanner
821
+ * compares `root` with the type symbol the model named for the same call: a
822
+ * model symbol that is not the stated root names something other than the
823
+ * body (an element of it, or a value the caller later computed from it), and
824
+ * the source's own statement outranks it.
825
+ */
826
+ export interface StatedBody {
827
+ /**
828
+ * The name the stated type is rooted at, once `Promise<...>`, array levels,
829
+ * parentheses and `| null`/`| undefined` are peeled: `Order` for
830
+ * `Promise<Order[] | null>`, `Page` for `Page<Order>`. Absent when the root
831
+ * is not a named type (an object literal type, a union of several types).
832
+ */
833
+ root?: string;
834
+ /** Declaration file (absolute path) of `root`, when it resolves to one. */
835
+ root_source?: string;
836
+ /** Array levels peeled on the way to `root`. Omitted when 0. */
837
+ array_depth?: number;
941
838
  }
942
839
  /**
943
840
  * Why a type carries `any`/`unknown` at a position, and where.
@@ -977,7 +874,6 @@ export interface SymbolFailure {
977
874
  }
978
875
  /**
979
876
  * Internal result from the bundler
980
- * @deprecated Use SurfaceEmitResult instead
981
877
  */
982
878
  export interface BundleResult {
983
879
  /** Whether bundling was successful */
@@ -991,21 +887,6 @@ export interface BundleResult {
991
887
  /** General error messages */
992
888
  errors?: string[];
993
889
  }
994
- /**
995
- * Internal result from surface emission
996
- */
997
- export interface SurfaceEmitResult {
998
- /** Whether emission was successful */
999
- success: boolean;
1000
- /** The emitted .d.ts content */
1001
- surface_content?: string;
1002
- /** Output path where content was written */
1003
- output_path?: string;
1004
- /** Manifest of emitted payloads */
1005
- manifest?: SurfaceManifestEntry[];
1006
- /** General error messages */
1007
- errors?: string[];
1008
- }
1009
890
  /**
1010
891
  * Internal result from the type inferrer
1011
892
  */
@@ -1017,32 +898,4 @@ export interface InferResult {
1017
898
  /** General error messages */
1018
899
  errors?: string[];
1019
900
  }
1020
- /**
1021
- * Result from building the synthetic workspace
1022
- */
1023
- export interface WorkspaceBuildResult {
1024
- /** Whether build was successful */
1025
- success: boolean;
1026
- /** Path to the workspace root */
1027
- workspace_path?: string;
1028
- /** Paths to stub packages */
1029
- stub_packages?: string[];
1030
- /** Path to the checker package */
1031
- checker_path?: string;
1032
- /** Error messages */
1033
- errors?: string[];
1034
- }
1035
- /**
1036
- * Result from running compatibility checks
1037
- */
1038
- export interface CompatibilityCheckResult {
1039
- /** Whether checks ran successfully (not whether types are compatible) */
1040
- success: boolean;
1041
- /** Individual check results */
1042
- results?: CompatibilityResult[];
1043
- /** TypeScript diagnostics */
1044
- diagnostics?: string[];
1045
- /** Error messages */
1046
- errors?: string[];
1047
- }
1048
901
  export {};