@suss/packs 0.34.0 → 0.34.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.
@@ -225,7 +225,25 @@ function activeRecordStorage(options) {
225
225
  classNameKeyword: "class_name"
226
226
  },
227
227
  scopes: ["scope"],
228
- storageSystem: options.storageSystem
228
+ storageSystem: options.storageSystem,
229
+ raises: [
230
+ {
231
+ exception: "ActiveRecord::RecordNotFound",
232
+ methods: [
233
+ "find",
234
+ "find_by!",
235
+ "find_sole_by",
236
+ "sole",
237
+ "first!",
238
+ "last!",
239
+ "take!"
240
+ ]
241
+ },
242
+ {
243
+ exception: "ActiveRecord::RecordInvalid",
244
+ methods: ["save!", "create!", "update!", "find_or_create_by!"]
245
+ }
246
+ ]
229
247
  }
230
248
  ];
231
249
  }
package/dist/aiohttp.js CHANGED
@@ -1,32 +1,43 @@
1
1
  // ../client/aiohttp/dist/index.js
2
- var VERB_METHODS = {
2
+ var VERB_METHODS_THAT_FOLLOW = {
3
3
  get: "GET",
4
4
  post: "POST",
5
5
  put: "PUT",
6
6
  patch: "PATCH",
7
7
  delete: "DELETE",
8
- head: "HEAD",
9
8
  options: "OPTIONS"
10
9
  };
10
+ function verbCalls(verbs, redirectDelivery) {
11
+ return {
12
+ type: "clientCall",
13
+ importModule: ["aiohttp"],
14
+ verbAttributeNames: verbs,
15
+ url: { position: 0, keyword: "url" },
16
+ receiverConstructors: ["ClientSession"],
17
+ response: {
18
+ redirectDelivery,
19
+ redirectOption: { name: "allow_redirects", handsBack: [false] }
20
+ }
21
+ };
22
+ }
11
23
  function aiohttpClient() {
12
24
  return {
13
25
  name: "aiohttp",
14
26
  protocol: "http",
15
27
  discovery: [],
28
+ // `head` defaults `allow_redirects` to False, and every other call,
29
+ // `request("HEAD", url)` included, defaults it to True.
16
30
  clients: [
17
31
  {
18
- type: "clientCall",
19
- importModule: ["aiohttp"],
20
- verbAttributeNames: VERB_METHODS,
21
- url: { position: 0, keyword: "url" },
32
+ ...verbCalls(VERB_METHODS_THAT_FOLLOW, "followed"),
22
33
  methodCall: {
23
34
  attribute: "request",
24
35
  methodPosition: 0,
25
36
  methodKeyword: "method",
26
37
  urlPosition: 1
27
- },
28
- receiverConstructors: ["ClientSession"]
29
- }
38
+ }
39
+ },
40
+ verbCalls({ head: "HEAD" }, "response")
30
41
  ],
31
42
  // `ClientSession.__aenter__` returns the session, so `async with
32
43
  // aiohttp.ClientSession() as s` puts the constructed session in s.
package/dist/axios.js CHANGED
@@ -23,7 +23,21 @@ var optionsSchema = z.object({
23
23
  */
24
24
  factories: z.array(clientFactory).optional()
25
25
  }).strict();
26
+ var CONFIG_POSITION = {
27
+ get: 1,
28
+ delete: 1,
29
+ head: 1,
30
+ options: 1,
31
+ post: 2,
32
+ put: 2,
33
+ patch: 2
34
+ };
26
35
  function discoveryForVerb(verb, factories) {
36
+ const bindingExtraction = {
37
+ method: { type: "literal", value: verb.toUpperCase() },
38
+ path: { type: "fromArgument", position: 0 },
39
+ options: { position: CONFIG_POSITION[verb] }
40
+ };
27
41
  const patterns = [
28
42
  {
29
43
  // Matches `axios.<verb>(path)` and `api.<verb>(path)`. factoryMethods
@@ -38,10 +52,7 @@ function discoveryForVerb(verb, factories) {
38
52
  factoryMethods: ["create"],
39
53
  basePathOption: "baseURL"
40
54
  },
41
- bindingExtraction: {
42
- method: { type: "literal", value: verb.toUpperCase() },
43
- path: { type: "fromArgument", position: 0 }
44
- },
55
+ bindingExtraction,
45
56
  requiresImport: ["axios"]
46
57
  }
47
58
  ];
@@ -55,10 +66,7 @@ function discoveryForVerb(verb, factories) {
55
66
  methodFilter: [verb],
56
67
  basePathOption: "baseURL"
57
68
  },
58
- bindingExtraction: {
59
- method: { type: "literal", value: verb.toUpperCase() },
60
- path: { type: "fromArgument", position: 0 }
61
- },
69
+ bindingExtraction,
62
70
  // Each importing file spells a relative path differently, so the
63
71
  // import-text prefilter cannot match one and a path-shaped factory
64
72
  // walks every file. The README has the details.
@@ -78,7 +86,8 @@ function configCallDiscovery(factories) {
78
86
  property: "method",
79
87
  default: "GET"
80
88
  },
81
- path: { type: "fromArgumentProperty", position: 0, property: "url" }
89
+ path: { type: "fromArgumentProperty", position: 0, property: "url" },
90
+ options: { position: 0 }
82
91
  };
83
92
  const patterns = [
84
93
  {
@@ -146,7 +155,11 @@ function axiosPack(options = {}) {
146
155
  ],
147
156
  // axios rejects on a non-2xx status, so every failure reaches the
148
157
  // caller's catch block instead of coming back as a response.
149
- failureDelivery: "exception"
158
+ failureDelivery: "exception",
159
+ // axios follows redirects unless the call or the instance sets
160
+ // `maxRedirects: 0`.
161
+ redirectDelivery: "followed",
162
+ redirectOption: { name: "maxRedirects", handsBack: [0] }
150
163
  };
151
164
  }
152
165
  var declares = {
package/dist/faraday.js CHANGED
@@ -28,7 +28,10 @@ function faradayClient() {
28
28
  statusCode: ["status"],
29
29
  success: ["success?"],
30
30
  body: ["body"],
31
- failureDelivery: "response"
31
+ failureDelivery: "response",
32
+ // Faraday follows a redirect only with the follow_redirects
33
+ // middleware added, so a plain connection hands the 3xx back.
34
+ redirectDelivery: "response"
32
35
  }
33
36
  }
34
37
  ]
package/dist/fastapi.js CHANGED
@@ -1,5 +1,83 @@
1
1
  // ../framework/fastapi/dist/index.js
2
2
  import { z } from "zod";
3
+ var STARLETTE_STATUS = {
4
+ HTTP_100_CONTINUE: 100,
5
+ HTTP_101_SWITCHING_PROTOCOLS: 101,
6
+ HTTP_102_PROCESSING: 102,
7
+ HTTP_103_EARLY_HINTS: 103,
8
+ HTTP_200_OK: 200,
9
+ HTTP_201_CREATED: 201,
10
+ HTTP_202_ACCEPTED: 202,
11
+ HTTP_203_NON_AUTHORITATIVE_INFORMATION: 203,
12
+ HTTP_204_NO_CONTENT: 204,
13
+ HTTP_205_RESET_CONTENT: 205,
14
+ HTTP_206_PARTIAL_CONTENT: 206,
15
+ HTTP_207_MULTI_STATUS: 207,
16
+ HTTP_208_ALREADY_REPORTED: 208,
17
+ HTTP_226_IM_USED: 226,
18
+ HTTP_300_MULTIPLE_CHOICES: 300,
19
+ HTTP_301_MOVED_PERMANENTLY: 301,
20
+ HTTP_302_FOUND: 302,
21
+ HTTP_303_SEE_OTHER: 303,
22
+ HTTP_304_NOT_MODIFIED: 304,
23
+ HTTP_305_USE_PROXY: 305,
24
+ HTTP_306_RESERVED: 306,
25
+ HTTP_307_TEMPORARY_REDIRECT: 307,
26
+ HTTP_308_PERMANENT_REDIRECT: 308,
27
+ HTTP_400_BAD_REQUEST: 400,
28
+ HTTP_401_UNAUTHORIZED: 401,
29
+ HTTP_402_PAYMENT_REQUIRED: 402,
30
+ HTTP_403_FORBIDDEN: 403,
31
+ HTTP_404_NOT_FOUND: 404,
32
+ HTTP_405_METHOD_NOT_ALLOWED: 405,
33
+ HTTP_406_NOT_ACCEPTABLE: 406,
34
+ HTTP_407_PROXY_AUTHENTICATION_REQUIRED: 407,
35
+ HTTP_408_REQUEST_TIMEOUT: 408,
36
+ HTTP_409_CONFLICT: 409,
37
+ HTTP_410_GONE: 410,
38
+ HTTP_411_LENGTH_REQUIRED: 411,
39
+ HTTP_412_PRECONDITION_FAILED: 412,
40
+ HTTP_413_REQUEST_ENTITY_TOO_LARGE: 413,
41
+ HTTP_413_CONTENT_TOO_LARGE: 413,
42
+ HTTP_414_REQUEST_URI_TOO_LONG: 414,
43
+ HTTP_414_URI_TOO_LONG: 414,
44
+ HTTP_415_UNSUPPORTED_MEDIA_TYPE: 415,
45
+ HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE: 416,
46
+ HTTP_416_RANGE_NOT_SATISFIABLE: 416,
47
+ HTTP_417_EXPECTATION_FAILED: 417,
48
+ HTTP_418_IM_A_TEAPOT: 418,
49
+ HTTP_421_MISDIRECTED_REQUEST: 421,
50
+ HTTP_422_UNPROCESSABLE_ENTITY: 422,
51
+ HTTP_422_UNPROCESSABLE_CONTENT: 422,
52
+ HTTP_423_LOCKED: 423,
53
+ HTTP_424_FAILED_DEPENDENCY: 424,
54
+ HTTP_425_TOO_EARLY: 425,
55
+ HTTP_426_UPGRADE_REQUIRED: 426,
56
+ HTTP_428_PRECONDITION_REQUIRED: 428,
57
+ HTTP_429_TOO_MANY_REQUESTS: 429,
58
+ HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
59
+ HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS: 451,
60
+ HTTP_500_INTERNAL_SERVER_ERROR: 500,
61
+ HTTP_501_NOT_IMPLEMENTED: 501,
62
+ HTTP_502_BAD_GATEWAY: 502,
63
+ HTTP_503_SERVICE_UNAVAILABLE: 503,
64
+ HTTP_504_GATEWAY_TIMEOUT: 504,
65
+ HTTP_505_HTTP_VERSION_NOT_SUPPORTED: 505,
66
+ HTTP_506_VARIANT_ALSO_NEGOTIATES: 506,
67
+ HTTP_507_INSUFFICIENT_STORAGE: 507,
68
+ HTTP_508_LOOP_DETECTED: 508,
69
+ HTTP_510_NOT_EXTENDED: 510,
70
+ HTTP_511_NETWORK_AUTHENTICATION_REQUIRED: 511
71
+ };
72
+ var STATUS_MODULES = ["fastapi.status", "starlette.status"];
73
+ var STATUS_CONSTANTS = Object.fromEntries(
74
+ STATUS_MODULES.flatMap(
75
+ (module) => Object.entries(STARLETTE_STATUS).map(([name, status]) => [
76
+ `${module}.${name}`,
77
+ status
78
+ ])
79
+ )
80
+ );
3
81
  var optionsSchema = z.object({
4
82
  /**
5
83
  * Modules that re-export FastAPI's constructors, on top of `fastapi`
@@ -31,6 +109,23 @@ var REQUEST_SPELLING = {
31
109
  params: { path: ["pathParams"], saysWhichField: true },
32
110
  body: { path: ["requestBody"], saysWhichField: true }
33
111
  };
112
+ var INJECTED_PARAMETER_TYPES = [
113
+ "fastapi.Request",
114
+ "fastapi.Response",
115
+ "fastapi.BackgroundTasks",
116
+ "fastapi.WebSocket",
117
+ "fastapi.requests.Request",
118
+ "fastapi.requests.HTTPConnection",
119
+ "fastapi.responses.Response",
120
+ "fastapi.background.BackgroundTasks",
121
+ "fastapi.websockets.WebSocket",
122
+ "fastapi.security.SecurityScopes",
123
+ "starlette.requests.Request",
124
+ "starlette.requests.HTTPConnection",
125
+ "starlette.responses.Response",
126
+ "starlette.background.BackgroundTasks",
127
+ "starlette.websockets.WebSocket"
128
+ ];
34
129
  function fastapiFramework(options = {}) {
35
130
  return {
36
131
  name: "fastapi",
@@ -47,12 +142,19 @@ function fastapiFramework(options = {}) {
47
142
  // FastAPI resolves both of these itself and calls the handler with
48
143
  // the result, so a parameter defaulted to one is never sent.
49
144
  injectedParameterCallees: ["Depends", "Security"],
145
+ // FastAPI also hands a route these objects by the annotation alone.
146
+ injectedParameterTypes: INJECTED_PARAMETER_TYPES,
50
147
  parameterSources: PARAMETER_SOURCES,
51
148
  parameterAliasKeyword: "alias",
52
149
  // FastAPI returns 200 for a route that declares no status.
53
150
  defaultStatusCode: 200,
151
+ // FastAPI checks every declared request input before the handler
152
+ // runs, and responds to a bad one itself.
153
+ validationFailureStatus: 422,
154
+ statusCodeConstants: STATUS_CONSTANTS,
54
155
  responseModelKeyword: "response_model",
55
156
  statusCodeKeyword: "status_code",
157
+ responsesKeyword: "responses",
56
158
  // FastAPI re-exports Starlette's class, and a project may import
57
159
  // it from either module.
58
160
  responseStatusCalls: [
package/dist/fetch.js CHANGED
@@ -19,7 +19,8 @@ function webFetchPack() {
19
19
  property: "method",
20
20
  default: "GET"
21
21
  },
22
- path: { type: "fromArgument", position: 0 }
22
+ path: { type: "fromArgument", position: 0 },
23
+ options: { position: 1 }
23
24
  },
24
25
  // `fetch` is a global, so there is no import to gate on. Walking
25
26
  // every file stays cheap because discovery only looks for calls
@@ -54,7 +55,12 @@ function webFetchPack() {
54
55
  { name: "text", access: "method", semantics: { type: "body" } },
55
56
  { name: "body", access: "property", semantics: { type: "body" } },
56
57
  { name: "headers", access: "property", semantics: { type: "headers" } }
57
- ]
58
+ ],
59
+ // fetch follows 301, 302, 303, 307 and 308, so the caller sees the
60
+ // final response, unless the call passes `redirect: "manual"` or
61
+ // `redirect: "error"`.
62
+ redirectDelivery: "followed",
63
+ redirectOption: { name: "redirect", handsBack: ["manual", "error"] }
58
64
  };
59
65
  }
60
66
  var declares = {
@@ -62,6 +68,7 @@ var declares = {
62
68
  package: "@suss/client-web",
63
69
  dependencies: [],
64
70
  shippedWith: "typescript",
71
+ sourcePattern: /(?:^|[^.\w$]|\b(?:window|globalThis|self)\.)fetch\s*\(/m,
65
72
  reads: "Global `fetch` call sites."
66
73
  };
67
74
  var index_default = webFetchPack;
package/dist/httpx.js CHANGED
@@ -32,7 +32,11 @@ function httpxClient() {
32
32
  statusCode: ["status_code"],
33
33
  success: ["is_success"],
34
34
  body: ["json", "text", "content"],
35
- failureDelivery: "response"
35
+ failureDelivery: "response",
36
+ // httpx hands a 3xx back unless the call passes
37
+ // `follow_redirects=True`.
38
+ redirectDelivery: "response",
39
+ redirectOption: { name: "follow_redirects", handsBack: [false] }
36
40
  }
37
41
  }
38
42
  ],
@@ -1,5 +1,68 @@
1
1
  // ../framework/nestjs-rest/dist/index.js
2
2
  import { z } from "zod";
3
+ var HTTP_STATUS = {
4
+ CONTINUE: 100,
5
+ SWITCHING_PROTOCOLS: 101,
6
+ PROCESSING: 102,
7
+ EARLYHINTS: 103,
8
+ OK: 200,
9
+ CREATED: 201,
10
+ ACCEPTED: 202,
11
+ NON_AUTHORITATIVE_INFORMATION: 203,
12
+ NO_CONTENT: 204,
13
+ RESET_CONTENT: 205,
14
+ PARTIAL_CONTENT: 206,
15
+ MULTI_STATUS: 207,
16
+ ALREADY_REPORTED: 208,
17
+ CONTENT_DIFFERENT: 210,
18
+ AMBIGUOUS: 300,
19
+ MOVED_PERMANENTLY: 301,
20
+ FOUND: 302,
21
+ SEE_OTHER: 303,
22
+ NOT_MODIFIED: 304,
23
+ TEMPORARY_REDIRECT: 307,
24
+ PERMANENT_REDIRECT: 308,
25
+ BAD_REQUEST: 400,
26
+ UNAUTHORIZED: 401,
27
+ PAYMENT_REQUIRED: 402,
28
+ FORBIDDEN: 403,
29
+ NOT_FOUND: 404,
30
+ METHOD_NOT_ALLOWED: 405,
31
+ NOT_ACCEPTABLE: 406,
32
+ PROXY_AUTHENTICATION_REQUIRED: 407,
33
+ REQUEST_TIMEOUT: 408,
34
+ CONFLICT: 409,
35
+ GONE: 410,
36
+ LENGTH_REQUIRED: 411,
37
+ PRECONDITION_FAILED: 412,
38
+ PAYLOAD_TOO_LARGE: 413,
39
+ URI_TOO_LONG: 414,
40
+ UNSUPPORTED_MEDIA_TYPE: 415,
41
+ REQUESTED_RANGE_NOT_SATISFIABLE: 416,
42
+ EXPECTATION_FAILED: 417,
43
+ I_AM_A_TEAPOT: 418,
44
+ MISDIRECTED: 421,
45
+ UNPROCESSABLE_ENTITY: 422,
46
+ LOCKED: 423,
47
+ FAILED_DEPENDENCY: 424,
48
+ PRECONDITION_REQUIRED: 428,
49
+ TOO_MANY_REQUESTS: 429,
50
+ UNRECOVERABLE_ERROR: 456,
51
+ INTERNAL_SERVER_ERROR: 500,
52
+ NOT_IMPLEMENTED: 501,
53
+ BAD_GATEWAY: 502,
54
+ SERVICE_UNAVAILABLE: 503,
55
+ GATEWAY_TIMEOUT: 504,
56
+ HTTP_VERSION_NOT_SUPPORTED: 505,
57
+ INSUFFICIENT_STORAGE: 507,
58
+ LOOP_DETECTED: 508
59
+ };
60
+ var HTTP_STATUS_CONSTANTS = Object.fromEntries(
61
+ Object.entries(HTTP_STATUS).map(([member, status]) => [
62
+ `HttpStatus.${member}`,
63
+ status
64
+ ])
65
+ );
3
66
  var optionsSchema = z.object({
4
67
  /**
5
68
  * Class decorators that wrap `@Controller()` in a package outside the
@@ -9,6 +72,11 @@ var optionsSchema = z.object({
9
72
  */
10
73
  classDecorators: z.array(z.string()).optional()
11
74
  }).strict();
75
+ var NEST_APPLICATION = {
76
+ importModule: "@nestjs/core",
77
+ importName: "NestFactory",
78
+ factory: "create"
79
+ };
12
80
  var REQUEST_METHODS = {
13
81
  0: "GET",
14
82
  1: "POST",
@@ -19,6 +87,57 @@ var REQUEST_METHODS = {
19
87
  6: "OPTIONS",
20
88
  7: "HEAD"
21
89
  };
90
+ var NEST_EXCEPTION_STATUSES = {
91
+ BadRequestException: 400,
92
+ UnauthorizedException: 401,
93
+ ForbiddenException: 403,
94
+ NotFoundException: 404,
95
+ MethodNotAllowedException: 405,
96
+ NotAcceptableException: 406,
97
+ RequestTimeoutException: 408,
98
+ ConflictException: 409,
99
+ GoneException: 410,
100
+ PreconditionFailedException: 412,
101
+ PayloadTooLargeException: 413,
102
+ UnsupportedMediaTypeException: 415,
103
+ ImATeapotException: 418,
104
+ MisdirectedException: 421,
105
+ UnprocessableEntityException: 422,
106
+ InternalServerErrorException: 500,
107
+ NotImplementedException: 501,
108
+ BadGatewayException: 502,
109
+ ServiceUnavailableException: 503,
110
+ GatewayTimeoutException: 504,
111
+ HttpVersionNotSupportedException: 505
112
+ };
113
+ var SWAGGER_RESPONSE_DECORATORS = {
114
+ ApiResponse: null,
115
+ ApiOkResponse: 200,
116
+ ApiCreatedResponse: 201,
117
+ ApiAcceptedResponse: 202,
118
+ ApiNoContentResponse: 204,
119
+ ApiMovedPermanentlyResponse: 301,
120
+ ApiFoundResponse: 302,
121
+ ApiBadRequestResponse: 400,
122
+ ApiUnauthorizedResponse: 401,
123
+ ApiForbiddenResponse: 403,
124
+ ApiNotFoundResponse: 404,
125
+ ApiMethodNotAllowedResponse: 405,
126
+ ApiNotAcceptableResponse: 406,
127
+ ApiRequestTimeoutResponse: 408,
128
+ ApiConflictResponse: 409,
129
+ ApiGoneResponse: 410,
130
+ ApiPreconditionFailedResponse: 412,
131
+ ApiPayloadTooLargeResponse: 413,
132
+ ApiUnsupportedMediaTypeResponse: 415,
133
+ ApiUnprocessableEntityResponse: 422,
134
+ ApiTooManyRequestsResponse: 429,
135
+ ApiInternalServerErrorResponse: 500,
136
+ ApiNotImplementedResponse: 501,
137
+ ApiBadGatewayResponse: 502,
138
+ ApiServiceUnavailableResponse: 503,
139
+ ApiGatewayTimeoutResponse: 504
140
+ };
22
141
  function nestjsRestFramework(options = {}) {
23
142
  return {
24
143
  name: "nestjs-rest",
@@ -47,13 +166,10 @@ function nestjsRestFramework(options = {}) {
47
166
  // `@HttpCode(n)` sets the status for one handler.
48
167
  defaultStatusCodes: { Post: 201 },
49
168
  statusCodeDecorator: "HttpCode",
169
+ statusCodeConstants: HTTP_STATUS_CONSTANTS,
50
170
  globalPrefix: {
51
171
  method: "setGlobalPrefix",
52
- application: {
53
- importModule: "@nestjs/core",
54
- importName: "NestFactory",
55
- factory: "create"
56
- },
172
+ application: NEST_APPLICATION,
57
173
  // An exclusion is a path, or a `RouteInfo` whose method is a
58
174
  // member of Nest's `RequestMethod` enum.
59
175
  exclude: {
@@ -62,6 +178,37 @@ function nestjsRestFramework(options = {}) {
62
178
  methodKey: "method",
63
179
  methods: REQUEST_METHODS
64
180
  }
181
+ },
182
+ // A spec `@nestjs/swagger` generates declares these statuses
183
+ // because of the decorators, whether or not a path sends them.
184
+ declaredStatuses: {
185
+ importModule: "@nestjs/swagger",
186
+ decorators: SWAGGER_RESPONSE_DECORATORS,
187
+ statusKey: "status"
188
+ },
189
+ // `app.enableVersioning()` with no options is URI versioning,
190
+ // which serves version 1 of a route at `/v1/...`.
191
+ versioning: {
192
+ option: "version",
193
+ decorator: "Version",
194
+ neutral: "VERSION_NEUTRAL",
195
+ call: { method: "enableVersioning", application: NEST_APPLICATION },
196
+ typeKey: "type",
197
+ types: {
198
+ "VersioningType.URI": "path",
199
+ "VersioningType.HEADER": "outsidePath",
200
+ "VersioningType.MEDIA_TYPE": "outsidePath",
201
+ "VersioningType.CUSTOM": "outsidePath"
202
+ },
203
+ typeNumbers: {
204
+ 0: "path",
205
+ 1: "outsidePath",
206
+ 2: "outsidePath",
207
+ 3: "outsidePath"
208
+ },
209
+ defaultType: "path",
210
+ pathPrefix: { key: "prefix", default: "v" },
211
+ defaultVersionKey: "defaultVersion"
65
212
  }
66
213
  },
67
214
  requiresImport: ["@nestjs/common"]
@@ -78,12 +225,15 @@ function nestjsRestFramework(options = {}) {
78
225
  }
79
226
  },
80
227
  {
81
- // `throw new BadRequestException()`: NestJS turns the exception
82
- // into a response. The throw records the exception type, and the
83
- // contract check pairs it with the status NestJS would send.
228
+ // `throw new BadRequestException()`: NestJS's exception filter
229
+ // sends the status that class is for. Any other throw keeps no
230
+ // status and stays a throw.
84
231
  kind: "throw",
85
232
  match: { type: "throwExpression" },
86
- extraction: {}
233
+ extraction: {
234
+ statusCode: { from: "constructor", codes: NEST_EXCEPTION_STATUSES }
235
+ },
236
+ producesResponse: true
87
237
  },
88
238
  {
89
239
  // A method that runs off the end returns undefined, and Nest
package/dist/net-http.js CHANGED
@@ -43,7 +43,9 @@ function netHttpClient() {
43
43
  response: {
44
44
  statusCode: ["code"],
45
45
  body: ["body"],
46
- failureDelivery: "response"
46
+ failureDelivery: "response",
47
+ // Net::HTTP never follows a redirect.
48
+ redirectDelivery: "response"
47
49
  }
48
50
  }
49
51
  ]
@@ -54,6 +56,7 @@ var declares = {
54
56
  package: "@suss/client-net-http",
55
57
  dependencies: [],
56
58
  shippedWith: "ruby",
59
+ sourcePattern: /\bNet::HTTP\b/,
57
60
  reads: "Net::HTTP call sites (Ruby): the module methods that send on their own, and a request object built with `Net::HTTP::Get` and its siblings, with the URL read through `URI`."
58
61
  };
59
62
  var index_default = netHttpClient;