carrick 0.3.131 → 0.3.133

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 (43) hide show
  1. package/dist/cli.d.ts +13 -1
  2. package/dist/cli.js +24 -3
  3. package/dist/cli.js.map +1 -1
  4. package/dist/contract.d.ts +12 -0
  5. package/dist/contract.js +18 -0
  6. package/dist/contract.js.map +1 -1
  7. package/dist/hook/post-edit.d.ts +5 -0
  8. package/dist/hook/post-edit.js +48 -15
  9. package/dist/hook/post-edit.js.map +1 -1
  10. package/dist/hook/session-start.d.ts +10 -1
  11. package/dist/hook/session-start.js +54 -4
  12. package/dist/hook/session-start.js.map +1 -1
  13. package/dist/init/agents-section.d.ts +17 -0
  14. package/dist/init/agents-section.js +88 -0
  15. package/dist/init/agents-section.js.map +1 -0
  16. package/dist/init/codex.js +13 -2
  17. package/dist/init/codex.js.map +1 -1
  18. package/dist/init/hosted.js +3 -1
  19. package/dist/init/hosted.js.map +1 -1
  20. package/dist/init/remove.d.ts +2 -0
  21. package/dist/init/remove.js +18 -0
  22. package/dist/init/remove.js.map +1 -1
  23. package/dist/init/run.js +12 -3
  24. package/dist/init/run.js.map +1 -1
  25. package/dist/init/settings.d.ts +2 -1
  26. package/dist/init/settings.js +32 -6
  27. package/dist/init/settings.js.map +1 -1
  28. package/package.json +6 -6
  29. package/plugin/.claude-plugin/plugin.json +1 -1
  30. package/sidecar/dist/src/absent-body.d.ts +41 -0
  31. package/sidecar/dist/src/absent-body.js +224 -0
  32. package/sidecar/dist/src/capture/api.d.ts +20 -0
  33. package/sidecar/dist/src/capture/check-probe.d.ts +5 -1
  34. package/sidecar/dist/src/capture/check-probe.js +38 -4
  35. package/sidecar/dist/src/capture/check-scrub.js +2 -0
  36. package/sidecar/dist/src/capture/check.js +8 -1
  37. package/sidecar/dist/src/capture/self-check.js +16 -6
  38. package/sidecar/dist/src/stated-params.d.ts +1 -1
  39. package/sidecar/dist/src/type-inferrer.d.ts +12 -0
  40. package/sidecar/dist/src/type-inferrer.js +47 -2
  41. package/sidecar/dist/src/types.d.ts +8 -0
  42. package/sidecar/dist/src/validators.d.ts +598 -578
  43. package/sidecar/dist/src/validators.js +2 -0
@@ -32,6 +32,7 @@ import { attributedDeclaration, installedPackageOf } from './declaration-attribu
32
32
  import { endLineOf, startLineOf } from './line-index.js';
33
33
  import { elapsedMs, inferTiming, phaseClock, timedPhase } from './infer-timing.js';
34
34
  import { StatedParams } from './stated-params.js';
35
+ import { bindingToleratesAbsence, handlerToleratesAbsentBody } from './absent-body.js';
35
36
  import { classifyStatusCodes, constituents, httpStatus, statesNoBody, statesNoShape, statusKeyCode, statusTableOf, successEntries, } from './capture/index.js';
36
37
  import { addedDiagnostics, applyInsertions, fileDiagnostics, literalInsertions, mapBack, mapForward, normalise, pathOf, } from './unwidened.js';
37
38
  import { expandTypeStructural, jsonWireType, } from './type-structural-expander.js';
@@ -883,7 +884,7 @@ export class TypeInferrer {
883
884
  case 'expression':
884
885
  return this.inferExpression(sourceFile, request, extractionConfig);
885
886
  case 'request_body':
886
- return this.inferRequestBody(sourceFile, request, extractionConfig);
887
+ return this.withAbsentBodyMark(sourceFile, request, this.inferRequestBody(sourceFile, request, extractionConfig));
887
888
  case 'signature_return':
888
889
  return this.inferSignatureReturn(sourceFile, request);
889
890
  case 'function_param':
@@ -1168,7 +1169,51 @@ export class TypeInferrer {
1168
1169
  // scanner re-aims the explicit bundle at the root symbol instead of
1169
1170
  // pasting this string, so the alias's definition stays self-contained.
1170
1171
  const anchor = this.unwrapArrayLevels(this.unwrapPromiseType(paramType));
1171
- return this.createInferredType(request, typeString, isExplicit, this.getNodeLocation(target.node), undefined, this.primaryTypeSymbol(anchor.element), anchor.depth, this.primaryTypeSymbolSource(anchor.element));
1172
+ const inferred = this.createInferredType(request, typeString, isExplicit, this.getNodeLocation(target.node), undefined, this.primaryTypeSymbol(anchor.element), anchor.depth, this.primaryTypeSymbolSource(anchor.element));
1173
+ // carrick#2814: a subscriber that defaults its payload, or reads it only
1174
+ // in ways `undefined` survives, still works when none is sent.
1175
+ const binding = Node.isBindingElement(target.node) ? target.node : target.param;
1176
+ if (bindingToleratesAbsence(binding)) {
1177
+ inferred.absent_body_tolerated = true;
1178
+ }
1179
+ return inferred;
1180
+ }
1181
+ /**
1182
+ * carrick#2814: mark a route's request body as one its handler tolerates
1183
+ * going unsent, when the handler is in reach and every read of the body
1184
+ * survives `undefined` (`absent-body.ts`). The check then lets a caller that
1185
+ * may send nothing call a route whose body type has no required member.
1186
+ *
1187
+ * No mark where the handler cannot be found, where a validator the
1188
+ * registration declares reads the body first (a schema, or another function
1189
+ * handed in beside the handler), or where the handler reads no body it can
1190
+ * see: the check keeps the reading it had.
1191
+ */
1192
+ withAbsentBodyMark(sourceFile, request, inferred) {
1193
+ if (!inferred)
1194
+ return inferred;
1195
+ const atLine = this.registrationAtLine(sourceFile, request.line_number);
1196
+ let registration = atLine?.registration;
1197
+ let handler = atLine?.handler;
1198
+ if (!handler) {
1199
+ const located = this.resolveTargetNode(sourceFile, request);
1200
+ handler = located ? this.registrationHandlerAt(located) : undefined;
1201
+ registration = handler && located ? this.unwrapExpressionNode(located) : undefined;
1202
+ }
1203
+ handler ??= this.exportedFunctionOpeningOn(sourceFile, request.line_number);
1204
+ if (!handler)
1205
+ return inferred;
1206
+ if (registration) {
1207
+ if (this.routeSchemaContract(registration, 'body') ?? this.validatedBodyContract(registration)) {
1208
+ return inferred;
1209
+ }
1210
+ if (this.statedParams.handsInAnotherFunction(registration, handler))
1211
+ return inferred;
1212
+ }
1213
+ if (handlerToleratesAbsentBody(handler)) {
1214
+ inferred.absent_body_tolerated = true;
1215
+ }
1216
+ return inferred;
1172
1217
  }
1173
1218
  /**
1174
1219
  * Resolve a `function_param` locator against a function's parameter list.
@@ -1228,6 +1228,14 @@ export interface InferredType {
1228
1228
  * Absent when the body is not a raw-text read.
1229
1229
  */
1230
1230
  raw_text_read?: true;
1231
+ /**
1232
+ * carrick#2814, a route's request body or a subscriber's payload: the
1233
+ * handler is in reach and works when nothing is sent, because it defaults
1234
+ * the body or reads it only in ways `undefined` survives (`?.`, `?? {}`).
1235
+ * Absent when the handler dereferences it, reads it through something not
1236
+ * seen, or was not found.
1237
+ */
1238
+ absent_body_tolerated?: true;
1231
1239
  /**
1232
1240
  * carrick#2054, a response joined from two or more success bodies: the
1233
1241
  * request fields whose values pick among them (`reads`), and, for one