@crvouga/mockingbird-service-google-maps 1.0.0 → 1.1.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.
@@ -463,7 +463,7 @@ var faultResponse = (rule) => {
463
463
  const body = rule.body === void 0 ? { detail: "Injected by Mockingbird" } : rule.body;
464
464
  return new Response(JSON.stringify(body), { status, headers });
465
465
  };
466
- var createFaultRegistry = (rng = createRng(0), sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))) => {
466
+ var createFaultRegistry = (rng = createRng(0), sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms))) => {
467
467
  const entries = [];
468
468
  return {
469
469
  add(rule) {
@@ -1149,6 +1149,16 @@ var operationMetadata = (operation) => {
1149
1149
 
1150
1150
  // ../core/dist/service.js
1151
1151
  import { Hono } from "hono";
1152
+
1153
+ // ../core/dist/validation.js
1154
+ var recorded = /* @__PURE__ */ new WeakMap();
1155
+ var recordedIssues = (request) => recorded.get(request);
1156
+
1157
+ // ../core/dist/service.js
1158
+ var withIssues = (request, response) => {
1159
+ const issues = response.status >= 400 ? recordedIssues(request) : void 0;
1160
+ return issues && issues.length > 0 ? annotateResponse(response, { issues }) : response;
1161
+ };
1152
1162
  var defineOperations = (handlers) => handlers;
1153
1163
  var OperationRegistryError = class extends Error {
1154
1164
  problems;
@@ -1234,9 +1244,7 @@ var createService = (options) => {
1234
1244
  now
1235
1245
  };
1236
1246
  const short = await options.before?.(context);
1237
- if (short)
1238
- return short;
1239
- return handler(context);
1247
+ return withIssues(request, short ?? await handler(context));
1240
1248
  };
1241
1249
  app.on(operation.method.toUpperCase(), honoPath(operation.path), route);
1242
1250
  }
@@ -1273,7 +1281,7 @@ var restoreNamespace = (sqlite, namespace, snapshot) => {
1273
1281
  };
1274
1282
 
1275
1283
  // ../core/dist/version.js
1276
- var PACKAGE_VERSION = true ? "1.0.0" : UNRELEASED_VERSION;
1284
+ var PACKAGE_VERSION = true ? "1.1.1" : UNRELEASED_VERSION;
1277
1285
 
1278
1286
  // ../core/dist/signing.js
1279
1287
  var encoder = new TextEncoder();
@@ -1441,7 +1449,7 @@ var createRuntime = (options) => {
1441
1449
  const rng = createRng(options.seed ?? 0);
1442
1450
  const wallNow = options.io?.wallNow ?? Date.now;
1443
1451
  const monotonicNow = options.io?.monotonicNow ?? (() => performance.now());
1444
- const sleep = options.io?.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
1452
+ const sleep = options.io?.sleep ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
1445
1453
  const faults = createFaultRegistry(createRng(options.seed ?? 0), sleep);
1446
1454
  const metrics = createMetrics();
1447
1455
  const journal = createJournal(options.journalSize ?? DEFAULT_JOURNAL_SIZE);
@@ -1724,8 +1732,15 @@ var createRuntime = (options) => {
1724
1732
  const started = monotonicNow();
1725
1733
  const url = new URL(request.url);
1726
1734
  const operationId = operationIdFor(request, url.pathname);
1735
+ const contentLength = request.headers.get("content-length");
1736
+ const received = {
1737
+ contentType: request.headers.get("content-type"),
1738
+ bodyBytes: contentLength !== null && /^\d+$/.test(contentLength) ? Number(contentLength) : null,
1739
+ transferEncoding: request.headers.get("transfer-encoding")
1740
+ };
1727
1741
  const log = (status, faultId, response2) => {
1728
1742
  const noted = response2 ? responseNotes(response2) : void 0;
1743
+ const rejected = status >= 400 && faultId === void 0;
1729
1744
  const entry = {
1730
1745
  service: options.name,
1731
1746
  namespace,
@@ -1737,7 +1752,9 @@ var createRuntime = (options) => {
1737
1752
  unmatched: options.document !== void 0 && operationId === void 0,
1738
1753
  ...faultId !== void 0 ? { faultId } : {},
1739
1754
  ...noted?.ids && Object.keys(noted.ids).length > 0 ? { ids: noted.ids } : {},
1740
- ...noted?.adopted ? { adopted: true } : {}
1755
+ ...noted?.adopted ? { adopted: true } : {},
1756
+ ...rejected ? { request: { ...received } } : {},
1757
+ ...rejected && noted?.issues && noted.issues.length > 0 ? { issues: noted.issues.map((issue) => ({ ...issue })) } : {}
1741
1758
  };
1742
1759
  metrics.record(entry);
1743
1760
  journal.record({ ...entry, at: new Date(clock.now()).toISOString() });
@@ -1945,9 +1962,9 @@ var presetRoutes = (presets, runtime) => ({
1945
1962
  });
1946
1963
 
1947
1964
  // src/generated/openapi.ts
1948
- var document = JSON.parse(`{"openapi":"3.1.0","info":{"title":"Google Places, Geocoding and Maps JavaScript API (Mockingbird subset)","description":"The Google Maps Platform surface our member app calls: Places Autocomplete, Place Details\\nand Find Place From Text (the legacy JSON web services), the Geocoding API, and the Maps\\nJavaScript API loader (\`/maps/api/js?libraries=places\`). Every web-service answer is HTTP 200\\nwith Google's \`status\` field; the mock resolves addresses from a QA corpus.\\n","version":"1","x-mockingbird-upstream":{"note":"Hand-authored from Google's documented response shapes and the fields our consumer reads (address-autocomplete-native-rest.tsx, address-autocomplete-web.tsx, use-geocoded-address.ts). Google publishes no OpenAPI document for these endpoints."}},"servers":[{"url":"https://maps.googleapis.com"}],"paths":{"/maps/api/place/autocomplete/json":{"get":{"operationId":"PlaceAutocomplete","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"$ref":"#/components/parameters/Key"},{"name":"input","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":60,"examples":["1625 N Central","Phoenix","85004","4821 Maple Street Denver","200 N Spring St, Los Angeles","136 Murray"]}},{"name":"types","in":"query","schema":{"type":"string","enum":["address","geocode"]}},{"name":"components","in":"query","schema":{"type":"string","enum":["country:us","country:ca","country:us|country:ca"]}},{"$ref":"#/components/parameters/SessionToken"}],"responses":{"200":{"description":"Predictions, or a non-OK status (HTTP 200 either way)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutocompleteResponse"}}}},"500":{"description":"Google front-end failure (server_error preset)","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/maps/api/place/details/json":{"get":{"operationId":"PlaceDetails","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"$ref":"#/components/parameters/Key"},{"name":"place_id","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":200,"examples":["ChIJ5BKAwJuCB5951g03ZzrkHx9","ChIJE1ellR5XyWiy2lHIlJ5cls3","ChIJaWYsCINV1XBQQ97jO3pznpg","EieyJsIjoiNDgyMSBNYXBsZSBTdHJlZXQiLCJjIjoiRGVudmVyIiwicyI6IkNPIiwieiI6IjgwMjAyIiwibiI6IkRlbnZlciBDb3VudHkiLCJhIjozOS43NDc4OCwibyI6LTEwNC45OTQyNX0","ChIJdoesNotExist000000000"]}},{"name":"fields","in":"query","schema":{"type":"string","enum":["address_component","address_components","geometry","formatted_address,geometry","place_id,name,types","address_component,geometry,formatted_address"]}},{"$ref":"#/components/parameters/SessionToken"}],"responses":{"200":{"description":"The place, or a non-OK status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DetailsResponse"}}}},"500":{"description":"Google front-end failure (server_error preset)","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/maps/api/geocode/json":{"get":{"operationId":"Geocode","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"$ref":"#/components/parameters/Key"},{"name":"address","in":"query","schema":{"type":"string","minLength":1,"maxLength":80,"examples":["1625 N Central Ave, Phoenix, AZ 85004","88 Greenwich St, New York, NY 10006","4821 Maple Street, Denver, CO 80202","85004","Phoenix, AZ","1625 N Central Ave"]}},{"name":"place_id","in":"query","schema":{"type":"string","examples":["ChIJ5BKAwJuCB5951g03ZzrkHx9"]}},{"name":"components","in":"query","schema":{"type":"string","enum":["postal_code:85004","postal_code:10006","postal_code:00000"]}}],"responses":{"200":{"description":"Geocoding results, or a non-OK status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeocodeResponse"}}}},"500":{"description":"Google front-end failure (server_error preset)","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/maps/api/place/findplacefromtext/json":{"get":{"operationId":"FindPlaceFromText","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"$ref":"#/components/parameters/Key"},{"name":"input","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":80,"examples":["1625 N Central Ave, Phoenix, AZ 85004","1625 N Central","Gilbert"]}},{"name":"inputtype","in":"query","required":true,"schema":{"type":"string","enum":["textquery","phonenumber"]}},{"name":"fields","in":"query","schema":{"type":"string","enum":["geometry","formatted_address,geometry","place_id,name","place_id"]}}],"responses":{"200":{"description":"Candidates, or a non-OK status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FindPlaceResponse"}}}},"500":{"description":"Google front-end failure (server_error preset)","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/maps/api/js":{"get":{"operationId":"MapsJavaScriptApi","description":"The Maps JavaScript API loader. The mock serves a shim defining google.maps.places (AutocompleteService, PlacesService, AutocompleteSessionToken, PlacesServiceStatus) and google.maps.Geocoder, backed by the REST operations above.","x-mockingbird":{"supported":true,"parity":{"enabled":false,"reason":"A JavaScript program, not data: it is exercised by evaluating it in a fake window and driving our web client through it (google-maps.acceptance.test.ts)."}},"parameters":[{"name":"key","in":"query","schema":{"type":"string"}},{"name":"libraries","in":"query","schema":{"type":"string"}},{"name":"callback","in":"query","schema":{"type":"string"}},{"name":"v","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"The Maps JavaScript shim","content":{"text/javascript":{"schema":{"type":"string"}}}},"503":{"description":"Script unavailable (script_unavailable preset)","content":{"text/plain":{"schema":{"type":"string"}}}}}}}},"components":{"parameters":{"Key":{"name":"key","in":"query","required":true,"description":"The Google Maps Platform API key (\`PLACES_KEY\`); also the namespace credential.","schema":{"type":"string","minLength":1,"maxLength":40,"examples":["parity-key"]}},"SessionToken":{"name":"sessiontoken","in":"query","description":"Autocomplete session token (billing grouping); accepted and journaled as metadata.","schema":{"type":"string","format":"uuid"}}},"schemas":{"Status":{"type":"string","enum":["OK","ZERO_RESULTS","INVALID_REQUEST","OVER_QUERY_LIMIT","REQUEST_DENIED","UNKNOWN_ERROR","NOT_FOUND"]},"LatLng":{"type":"object","required":["lat","lng"],"properties":{"lat":{"type":"number"},"lng":{"type":"number"}}},"Viewport":{"type":"object","required":["northeast","southwest"],"properties":{"northeast":{"$ref":"#/components/schemas/LatLng"},"southwest":{"$ref":"#/components/schemas/LatLng"}}},"Geometry":{"type":"object","required":["location","viewport"],"properties":{"location":{"$ref":"#/components/schemas/LatLng"},"location_type":{"type":"string","enum":["ROOFTOP","RANGE_INTERPOLATED","GEOMETRIC_CENTER","APPROXIMATE"]},"viewport":{"$ref":"#/components/schemas/Viewport"}}},"AddressComponent":{"type":"object","required":["long_name","short_name","types"],"properties":{"long_name":{"type":"string"},"short_name":{"type":"string"},"types":{"type":"array","items":{"type":"string"}}}},"MatchedSubstring":{"type":"object","required":["length","offset"],"properties":{"length":{"type":"integer"},"offset":{"type":"integer"}}},"Prediction":{"type":"object","required":["description","place_id","reference","structured_formatting","terms","types","matched_substrings"],"properties":{"description":{"type":"string"},"matched_substrings":{"type":"array","items":{"$ref":"#/components/schemas/MatchedSubstring"}},"place_id":{"type":"string","x-mockingbird-resource":{"type":"place","identity":true}},"reference":{"type":"string"},"structured_formatting":{"type":"object","required":["main_text","secondary_text"],"properties":{"main_text":{"type":"string"},"main_text_matched_substrings":{"type":"array","items":{"$ref":"#/components/schemas/MatchedSubstring"}},"secondary_text":{"type":"string"}}},"terms":{"type":"array","items":{"type":"object","required":["offset","value"],"properties":{"offset":{"type":"integer"},"value":{"type":"string"}}}},"types":{"type":"array","items":{"type":"string"}}}},"PlaceResult":{"type":"object","description":"Only the fields requested with \`fields=\` are present.","properties":{"address_components":{"type":"array","items":{"$ref":"#/components/schemas/AddressComponent"}},"adr_address":{"type":"string"},"formatted_address":{"type":"string"},"geometry":{"$ref":"#/components/schemas/Geometry"},"name":{"type":"string"},"place_id":{"type":"string"},"reference":{"type":"string"},"types":{"type":"array","items":{"type":"string"}},"url":{"type":"string"},"utc_offset":{"type":"integer"},"vicinity":{"type":"string"}}},"AutocompleteResponse":{"type":"object","required":["predictions","status"],"properties":{"predictions":{"type":"array","items":{"$ref":"#/components/schemas/Prediction"}},"status":{"$ref":"#/components/schemas/Status"},"error_message":{"type":"string"}}},"DetailsResponse":{"type":"object","required":["html_attributions","status"],"properties":{"html_attributions":{"type":"array","items":{"type":"string"}},"result":{"$ref":"#/components/schemas/PlaceResult"},"status":{"$ref":"#/components/schemas/Status"},"error_message":{"type":"string"}}},"GeocodeResult":{"type":"object","required":["address_components","formatted_address","geometry","place_id","types"],"properties":{"address_components":{"type":"array","items":{"$ref":"#/components/schemas/AddressComponent"}},"formatted_address":{"type":"string"},"geometry":{"$ref":"#/components/schemas/Geometry"},"place_id":{"type":"string"},"types":{"type":"array","items":{"type":"string"}}}},"GeocodeResponse":{"type":"object","required":["results","status"],"properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/GeocodeResult"}},"status":{"$ref":"#/components/schemas/Status"},"error_message":{"type":"string"}}},"FindPlaceResponse":{"type":"object","required":["candidates","status"],"properties":{"candidates":{"type":"array","items":{"$ref":"#/components/schemas/PlaceResult"}},"status":{"$ref":"#/components/schemas/Status"},"error_message":{"type":"string"}}}}}}`);
1949
- var operationIds = ["PlaceAutocomplete", "PlaceDetails", "Geocode", "FindPlaceFromText", "MapsJavaScriptApi"];
1950
- var supportedOperationIds = ["PlaceAutocomplete", "PlaceDetails", "Geocode", "FindPlaceFromText", "MapsJavaScriptApi"];
1965
+ var document = JSON.parse(`{"openapi":"3.1.0","info":{"title":"Google Places, Geocoding and Maps JavaScript API (Mockingbird subset)","description":"The Google Maps Platform surface our member app calls: Places Autocomplete, Place Details\\nand Find Place From Text (the legacy JSON web services), the Geocoding API, and the Maps\\nJavaScript API loader (\`/maps/api/js?libraries=places\`). Every web-service answer is HTTP 200\\nwith Google's \`status\` field; the mock resolves addresses from a QA corpus.\\n","version":"1","x-mockingbird-upstream":{"note":"Hand-authored from Google's documented response shapes and the fields our consumer reads (address-autocomplete-native-rest.tsx, address-autocomplete-web.tsx, use-geocoded-address.ts). Google publishes no OpenAPI document for these endpoints."}},"servers":[{"url":"https://maps.googleapis.com"}],"paths":{"/maps/api/place/autocomplete/json":{"get":{"operationId":"PlaceAutocomplete","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"$ref":"#/components/parameters/Key"},{"name":"input","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":60,"examples":["1625 N Central","Phoenix","85004","4821 Maple Street Denver","200 N Spring St, Los Angeles","136 Murray"]}},{"name":"types","in":"query","schema":{"type":"string","enum":["address","geocode"]}},{"name":"components","in":"query","schema":{"type":"string","enum":["country:us","country:ca","country:us|country:ca"]}},{"$ref":"#/components/parameters/SessionToken"}],"responses":{"200":{"description":"Predictions, or a non-OK status (HTTP 200 either way)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutocompleteResponse"}}}},"500":{"description":"Google front-end failure (server_error preset)","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/maps/api/place/details/json":{"get":{"operationId":"PlaceDetails","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"$ref":"#/components/parameters/Key"},{"name":"place_id","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":200,"examples":["ChIJ5BKAwJuCB5951g03ZzrkHx9","ChIJE1ellR5XyWiy2lHIlJ5cls3","ChIJaWYsCINV1XBQQ97jO3pznpg","EieyJsIjoiNDgyMSBNYXBsZSBTdHJlZXQiLCJjIjoiRGVudmVyIiwicyI6IkNPIiwieiI6IjgwMjAyIiwibiI6IkRlbnZlciBDb3VudHkiLCJhIjozOS43NDc4OCwibyI6LTEwNC45OTQyNX0","ChIJdoesNotExist000000000"]}},{"name":"fields","in":"query","schema":{"type":"string","enum":["address_component","address_components","geometry","formatted_address,geometry","place_id,name,types","address_component,geometry,formatted_address"]}},{"$ref":"#/components/parameters/SessionToken"}],"responses":{"200":{"description":"The place, or a non-OK status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DetailsResponse"}}}},"500":{"description":"Google front-end failure (server_error preset)","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/maps/api/geocode/json":{"get":{"operationId":"Geocode","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"$ref":"#/components/parameters/Key"},{"name":"address","in":"query","schema":{"type":"string","minLength":1,"maxLength":80,"examples":["1625 N Central Ave, Phoenix, AZ 85004","88 Greenwich St, New York, NY 10006","4821 Maple Street, Denver, CO 80202","85004","Phoenix, AZ","1625 N Central Ave"]}},{"name":"place_id","in":"query","schema":{"type":"string","examples":["ChIJ5BKAwJuCB5951g03ZzrkHx9"]}},{"name":"components","in":"query","schema":{"type":"string","enum":["postal_code:85004","postal_code:10006","postal_code:00000"]}}],"responses":{"200":{"description":"Geocoding results, or a non-OK status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeocodeResponse"}}}},"500":{"description":"Google front-end failure (server_error preset)","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/maps/api/place/findplacefromtext/json":{"get":{"operationId":"FindPlaceFromText","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"$ref":"#/components/parameters/Key"},{"name":"input","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":80,"examples":["1625 N Central Ave, Phoenix, AZ 85004","1625 N Central","Gilbert"]}},{"name":"inputtype","in":"query","required":true,"schema":{"type":"string","enum":["textquery","phonenumber"]}},{"name":"fields","in":"query","schema":{"type":"string","enum":["geometry","formatted_address,geometry","place_id,name","place_id"]}}],"responses":{"200":{"description":"Candidates, or a non-OK status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FindPlaceResponse"}}}},"500":{"description":"Google front-end failure (server_error preset)","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/maps/api/js":{"get":{"operationId":"MapsJavaScriptApi","description":"The Maps JavaScript API loader. The mock serves a shim defining google.maps.places (AutocompleteService, PlacesService, AutocompleteSessionToken, PlacesServiceStatus) and google.maps.Geocoder, backed by the REST operations above.","x-mockingbird":{"supported":true,"parity":{"enabled":false,"reason":"A JavaScript program, not data: it is exercised by evaluating it in a fake window and driving our web client through it (google-maps.acceptance.test.ts)."}},"parameters":[{"name":"key","in":"query","schema":{"type":"string"}},{"name":"libraries","in":"query","schema":{"type":"string"}},{"name":"callback","in":"query","schema":{"type":"string"}},{"name":"v","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"The Maps JavaScript shim","content":{"text/javascript":{"schema":{"type":"string"}}}},"503":{"description":"Script unavailable (script_unavailable preset)","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/v1:validateAddress":{"servers":[{"url":"https://addressvalidation.googleapis.com"}],"post":{"operationId":"ValidateAddress","description":"Address Validation API v1 validateAddress, with USPS CASS data (\`enableUspsCass\`). A Google Cloud API: errors are HTTP 4xx/5xx with a \`google.rpc.Status\` envelope, and the key may also be sent as the \`X-Goog-Api-Key\` header. Responses are proto3 JSON (false booleans and empty lists omitted). Reference: https://developers.google.com/maps/documentation/address-validation/reference/rest/v1/TopLevel/validateAddress","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"$ref":"#/components/parameters/Key"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateAddressRequest"}}}},"responses":{"200":{"description":"The validation result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateAddressResponse"}}}},"400":{"description":"INVALID_ARGUMENT (malformed request, unsupported region, invalid API key)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleApiError"}}}},"403":{"description":"PERMISSION_DENIED (missing key; address_validation_denied preset)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleApiError"}}}},"503":{"description":"UNAVAILABLE (address_validation_unavailable preset)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleApiError"}}}}}}}},"components":{"parameters":{"Key":{"name":"key","in":"query","required":true,"description":"The Google Maps Platform API key (\`PLACES_KEY\`); also the namespace credential.","schema":{"type":"string","minLength":1,"maxLength":40,"examples":["parity-key"]}},"SessionToken":{"name":"sessiontoken","in":"query","description":"Autocomplete session token (billing grouping); accepted and journaled as metadata.","schema":{"type":"string","format":"uuid"}}},"schemas":{"Status":{"type":"string","enum":["OK","ZERO_RESULTS","INVALID_REQUEST","OVER_QUERY_LIMIT","REQUEST_DENIED","UNKNOWN_ERROR","NOT_FOUND"]},"LatLng":{"type":"object","required":["lat","lng"],"properties":{"lat":{"type":"number"},"lng":{"type":"number"}}},"Viewport":{"type":"object","required":["northeast","southwest"],"properties":{"northeast":{"$ref":"#/components/schemas/LatLng"},"southwest":{"$ref":"#/components/schemas/LatLng"}}},"Geometry":{"type":"object","required":["location","viewport"],"properties":{"location":{"$ref":"#/components/schemas/LatLng"},"location_type":{"type":"string","enum":["ROOFTOP","RANGE_INTERPOLATED","GEOMETRIC_CENTER","APPROXIMATE"]},"viewport":{"$ref":"#/components/schemas/Viewport"}}},"AddressComponent":{"type":"object","required":["long_name","short_name","types"],"properties":{"long_name":{"type":"string"},"short_name":{"type":"string"},"types":{"type":"array","items":{"type":"string"}}}},"MatchedSubstring":{"type":"object","required":["length","offset"],"properties":{"length":{"type":"integer"},"offset":{"type":"integer"}}},"Prediction":{"type":"object","required":["description","place_id","reference","structured_formatting","terms","types","matched_substrings"],"properties":{"description":{"type":"string"},"matched_substrings":{"type":"array","items":{"$ref":"#/components/schemas/MatchedSubstring"}},"place_id":{"type":"string","x-mockingbird-resource":{"type":"place","identity":true}},"reference":{"type":"string"},"structured_formatting":{"type":"object","required":["main_text","secondary_text"],"properties":{"main_text":{"type":"string"},"main_text_matched_substrings":{"type":"array","items":{"$ref":"#/components/schemas/MatchedSubstring"}},"secondary_text":{"type":"string"}}},"terms":{"type":"array","items":{"type":"object","required":["offset","value"],"properties":{"offset":{"type":"integer"},"value":{"type":"string"}}}},"types":{"type":"array","items":{"type":"string"}}}},"PlaceResult":{"type":"object","description":"Only the fields requested with \`fields=\` are present.","properties":{"address_components":{"type":"array","items":{"$ref":"#/components/schemas/AddressComponent"}},"adr_address":{"type":"string"},"formatted_address":{"type":"string"},"geometry":{"$ref":"#/components/schemas/Geometry"},"name":{"type":"string"},"place_id":{"type":"string"},"reference":{"type":"string"},"types":{"type":"array","items":{"type":"string"}},"url":{"type":"string"},"utc_offset":{"type":"integer"},"vicinity":{"type":"string"}}},"AutocompleteResponse":{"type":"object","required":["predictions","status"],"properties":{"predictions":{"type":"array","items":{"$ref":"#/components/schemas/Prediction"}},"status":{"$ref":"#/components/schemas/Status"},"error_message":{"type":"string"}}},"DetailsResponse":{"type":"object","required":["html_attributions","status"],"properties":{"html_attributions":{"type":"array","items":{"type":"string"}},"result":{"$ref":"#/components/schemas/PlaceResult"},"status":{"$ref":"#/components/schemas/Status"},"error_message":{"type":"string"}}},"GeocodeResult":{"type":"object","required":["address_components","formatted_address","geometry","place_id","types"],"properties":{"address_components":{"type":"array","items":{"$ref":"#/components/schemas/AddressComponent"}},"formatted_address":{"type":"string"},"geometry":{"$ref":"#/components/schemas/Geometry"},"place_id":{"type":"string"},"types":{"type":"array","items":{"type":"string"}}}},"GeocodeResponse":{"type":"object","required":["results","status"],"properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/GeocodeResult"}},"status":{"$ref":"#/components/schemas/Status"},"error_message":{"type":"string"}}},"FindPlaceResponse":{"type":"object","required":["candidates","status"],"properties":{"candidates":{"type":"array","items":{"$ref":"#/components/schemas/PlaceResult"}},"status":{"$ref":"#/components/schemas/Status"},"error_message":{"type":"string"}}},"GoogleApiError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","status"],"properties":{"code":{"type":"integer"},"message":{"type":"string"},"status":{"type":"string"},"details":{"type":"array","items":{"type":"object"}}}}}},"PostalAddress":{"type":"object","description":"google.type.PostalAddress","properties":{"revision":{"type":"integer"},"regionCode":{"type":"string","examples":["US"]},"languageCode":{"type":"string"},"postalCode":{"type":"string","examples":["85004","10006","80202","90012","00000"]},"sortingCode":{"type":"string"},"administrativeArea":{"type":"string","examples":["AZ","NY","CO","CA"]},"locality":{"type":"string","examples":["Phoenix","New York","Denver","Los Angeles","Springfield"]},"sublocality":{"type":"string"},"addressLines":{"type":"array","maxItems":3,"items":{"type":"string","maxLength":80,"examples":["1625 N Central Ave","1625 North Central Avenue Building A","4821 Maple Street","N Central Ave","Apt 2"]}},"recipients":{"type":"array","items":{"type":"string"}},"organization":{"type":"string"}}},"ValidateAddressRequest":{"type":"object","required":["address"],"additionalProperties":false,"properties":{"address":{"$ref":"#/components/schemas/PostalAddress","examples":[{"regionCode":"US","addressLines":["1625 N Central Ave"],"locality":"Phoenix","administrativeArea":"AZ","postalCode":"85004"},{"regionCode":"US","addressLines":["4821 Maple Street"],"locality":"Denver","administrativeArea":"CO","postalCode":"80202"},{"regionCode":"US","addressLines":["N Central Ave"],"locality":"Phoenix","administrativeArea":"AZ","postalCode":"85004"},{"regionCode":"US","addressLines":["1625 N Central Ave, Phoenix, AZ 85004"]},{"regionCode":"US","addressLines":["12 Nowhere Rd"],"locality":"Springfield","administrativeArea":"ZZ","postalCode":"00000"}]},"previousResponseId":{"type":"string"},"enableUspsCass":{"type":"boolean"},"languageOptions":{"type":"object"},"sessionToken":{"type":"string"}}},"ValidationAddressComponent":{"type":"object","required":["componentName","componentType","confirmationLevel"],"properties":{"componentName":{"type":"object","required":["text"],"properties":{"text":{"type":"string"},"languageCode":{"type":"string"}}},"componentType":{"type":"string"},"confirmationLevel":{"type":"string","enum":["CONFIRMED","UNCONFIRMED_BUT_PLAUSIBLE","UNCONFIRMED_AND_SUSPICIOUS"]},"inferred":{"type":"boolean"},"spellCorrected":{"type":"boolean"},"replaced":{"type":"boolean"},"unexpected":{"type":"boolean"}}},"Granularity":{"type":"string","enum":["GRANULARITY_UNSPECIFIED","SUB_PREMISE","PREMISE","PREMISE_PROXIMITY","BLOCK","ROUTE","OTHER"]},"ValidationResult":{"type":"object","properties":{"verdict":{"type":"object","properties":{"inputGranularity":{"$ref":"#/components/schemas/Granularity"},"validationGranularity":{"$ref":"#/components/schemas/Granularity"},"geocodeGranularity":{"$ref":"#/components/schemas/Granularity"},"addressComplete":{"type":"boolean"},"hasUnconfirmedComponents":{"type":"boolean"},"hasInferredComponents":{"type":"boolean"},"hasReplacedComponents":{"type":"boolean"},"hasSpellCorrectedComponents":{"type":"boolean"},"possibleNextAction":{"type":"string","enum":["POSSIBLE_NEXT_ACTION_UNSPECIFIED","FIX","CONFIRM_ADD_SUBPREMISES","CONFIRM","ACCEPT"]}}},"address":{"type":"object","properties":{"formattedAddress":{"type":"string"},"postalAddress":{"$ref":"#/components/schemas/PostalAddress"},"addressComponents":{"type":"array","items":{"$ref":"#/components/schemas/ValidationAddressComponent"}},"missingComponentTypes":{"type":"array","items":{"type":"string"}},"unconfirmedComponentTypes":{"type":"array","items":{"type":"string"}},"unresolvedTokens":{"type":"array","items":{"type":"string"}}}},"geocode":{"type":"object","properties":{"location":{"type":"object","properties":{"latitude":{"type":"number"},"longitude":{"type":"number"}}},"placeId":{"type":"string"},"placeTypes":{"type":"array","items":{"type":"string"}}}},"uspsData":{"type":"object","properties":{"standardizedAddress":{"type":"object","properties":{"firstAddressLine":{"type":"string"},"secondAddressLine":{"type":"string"},"cityStateZipAddressLine":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zipCode":{"type":"string"},"zipCodeExtension":{"type":"string"}}},"dpvConfirmation":{"type":"string","enum":["Y","N","S","D"]},"dpvFootnote":{"type":"string"},"postOfficeCity":{"type":"string"},"postOfficeState":{"type":"string"},"errorMessage":{"type":"string"},"cassProcessed":{"type":"boolean"}}}}},"ValidateAddressResponse":{"type":"object","required":["result","responseId"],"properties":{"result":{"$ref":"#/components/schemas/ValidationResult"},"responseId":{"type":"string"}}}}}}`);
1966
+ var operationIds = ["PlaceAutocomplete", "PlaceDetails", "Geocode", "FindPlaceFromText", "MapsJavaScriptApi", "ValidateAddress"];
1967
+ var supportedOperationIds = ["PlaceAutocomplete", "PlaceDetails", "Geocode", "FindPlaceFromText", "MapsJavaScriptApi", "ValidateAddress"];
1951
1968
 
1952
1969
  // src/corpus.ts
1953
1970
  var row = (id, line1, city, state, zip, county, lat, lng) => ({ id, line1, city, state, zip, county, lat, lng });
@@ -3010,6 +3027,541 @@ var GoogleMapsState = class {
3010
3027
  }
3011
3028
  };
3012
3029
 
3030
+ // src/validation.ts
3031
+ var GRANULARITIES = [
3032
+ "SUB_PREMISE",
3033
+ "PREMISE",
3034
+ "PREMISE_PROXIMITY",
3035
+ "BLOCK",
3036
+ "ROUTE",
3037
+ "OTHER"
3038
+ ];
3039
+ var NEXT_ACTIONS = [
3040
+ "FIX",
3041
+ "CONFIRM_ADD_SUBPREMISES",
3042
+ "CONFIRM",
3043
+ "ACCEPT"
3044
+ ];
3045
+ var DPV_CODES = ["Y", "N", "S", "D"];
3046
+ var ValidationRequestError = class extends Error {
3047
+ constructor(message) {
3048
+ super(message);
3049
+ this.name = "ValidationRequestError";
3050
+ }
3051
+ };
3052
+ var TOP_LEVEL = /* @__PURE__ */ new Set([
3053
+ "address",
3054
+ "previousResponseId",
3055
+ "enableUspsCass",
3056
+ "languageOptions",
3057
+ "sessionToken"
3058
+ ]);
3059
+ var POSTAL_ADDRESS = /* @__PURE__ */ new Set([
3060
+ "revision",
3061
+ "regionCode",
3062
+ "languageCode",
3063
+ "postalCode",
3064
+ "sortingCode",
3065
+ "administrativeArea",
3066
+ "locality",
3067
+ "sublocality",
3068
+ "addressLines",
3069
+ "recipients",
3070
+ "organization"
3071
+ ]);
3072
+ var MAX_INPUT_LENGTH = 280;
3073
+ var MAX_ADDRESS_LINES = 3;
3074
+ var MAX_ADDRESS_LINE_LENGTH = 80;
3075
+ var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
3076
+ var optionalString = (value, field) => {
3077
+ if (value === void 0 || value === null) return void 0;
3078
+ if (typeof value !== "string") {
3079
+ throw new ValidationRequestError(
3080
+ `Invalid value at '${field}' (TYPE_STRING), ${JSON.stringify(value)}`
3081
+ );
3082
+ }
3083
+ const trimmed = value.trim();
3084
+ return trimmed ? trimmed : void 0;
3085
+ };
3086
+ var parseValidateRequest = (body) => {
3087
+ if (!isRecord4(body)) throw new ValidationRequestError("Invalid JSON payload received.");
3088
+ for (const key of Object.keys(body)) {
3089
+ if (!TOP_LEVEL.has(key)) {
3090
+ throw new ValidationRequestError(
3091
+ `Invalid JSON payload received. Unknown name "${key}": Cannot find field.`
3092
+ );
3093
+ }
3094
+ }
3095
+ const address = body.address;
3096
+ if (address === void 0 || address === null) {
3097
+ throw new ValidationRequestError("Address is missing from the request.");
3098
+ }
3099
+ if (!isRecord4(address)) {
3100
+ throw new ValidationRequestError(
3101
+ `Invalid value at 'address' (type.googleapis.com/google.type.PostalAddress), ${JSON.stringify(address)}`
3102
+ );
3103
+ }
3104
+ for (const key of Object.keys(address)) {
3105
+ if (!POSTAL_ADDRESS.has(key)) {
3106
+ throw new ValidationRequestError(
3107
+ `Invalid JSON payload received. Unknown name "${key}" at 'address': Cannot find field.`
3108
+ );
3109
+ }
3110
+ }
3111
+ const rawLines = address.addressLines ?? [];
3112
+ if (!Array.isArray(rawLines) || rawLines.some((line) => typeof line !== "string")) {
3113
+ throw new ValidationRequestError(
3114
+ `Invalid value at 'address.address_lines' (TYPE_STRING), ${JSON.stringify(rawLines)}`
3115
+ );
3116
+ }
3117
+ if (rawLines.length > MAX_ADDRESS_LINES) {
3118
+ throw new ValidationRequestError(
3119
+ `Invalid value at 'address.address_lines' (repeated STRING), a maximum of ${MAX_ADDRESS_LINES} address lines is allowed.`
3120
+ );
3121
+ }
3122
+ const overLong = rawLines.findIndex((line) => line.length > MAX_ADDRESS_LINE_LENGTH);
3123
+ if (overLong !== -1) {
3124
+ throw new ValidationRequestError(
3125
+ `Invalid value at 'address.address_lines[${overLong}]' (STRING), the maximum length is ${MAX_ADDRESS_LINE_LENGTH} characters.`
3126
+ );
3127
+ }
3128
+ const addressLines = rawLines.map((line) => line.trim()).filter(Boolean);
3129
+ if (addressLines.length === 0) {
3130
+ throw new ValidationRequestError("Address lines are missing from the request.");
3131
+ }
3132
+ const enable = body.enableUspsCass;
3133
+ if (enable !== void 0 && enable !== null && typeof enable !== "boolean") {
3134
+ throw new ValidationRequestError(
3135
+ `Invalid value at 'enable_usps_cass' (TYPE_BOOL), ${JSON.stringify(enable)}`
3136
+ );
3137
+ }
3138
+ const input = {
3139
+ regionCode: optionalString(address.regionCode, "address.region_code")?.toUpperCase(),
3140
+ addressLines,
3141
+ locality: optionalString(address.locality, "address.locality"),
3142
+ administrativeArea: optionalString(address.administrativeArea, "address.administrative_area"),
3143
+ postalCode: optionalString(address.postalCode, "address.postal_code")
3144
+ };
3145
+ const length = [
3146
+ ...input.addressLines,
3147
+ input.locality ?? "",
3148
+ input.administrativeArea ?? "",
3149
+ input.postalCode ?? ""
3150
+ ].join("").length;
3151
+ if (length > MAX_INPUT_LENGTH) {
3152
+ throw new ValidationRequestError(
3153
+ `The total length of the address fields must not exceed ${MAX_INPUT_LENGTH} characters.`
3154
+ );
3155
+ }
3156
+ const region = input.regionCode ?? "US";
3157
+ if (enable === true && region !== "US" && region !== "PR") {
3158
+ throw new ValidationRequestError(
3159
+ "USPS CASS validation is only supported for addresses in the US and PR regions."
3160
+ );
3161
+ }
3162
+ return { address: input, enableUspsCass: enable === true };
3163
+ };
3164
+ var ABBREVIATIONS = {
3165
+ north: "N",
3166
+ south: "S",
3167
+ east: "E",
3168
+ west: "W",
3169
+ northeast: "NE",
3170
+ northwest: "NW",
3171
+ southeast: "SE",
3172
+ southwest: "SW",
3173
+ avenue: "Ave",
3174
+ av: "Ave",
3175
+ street: "St",
3176
+ str: "St",
3177
+ road: "Rd",
3178
+ drive: "Dr",
3179
+ boulevard: "Blvd",
3180
+ lane: "Ln",
3181
+ parkway: "Pkwy",
3182
+ place: "Pl",
3183
+ court: "Ct",
3184
+ circle: "Cir",
3185
+ highway: "Hwy",
3186
+ terrace: "Ter",
3187
+ square: "Sq",
3188
+ plaza: "Plz",
3189
+ trail: "Trl",
3190
+ way: "Way",
3191
+ mall: "Mall"
3192
+ };
3193
+ var DIRECTIONALS = /* @__PURE__ */ new Set(["n", "s", "e", "w", "ne", "nw", "se", "sw"]);
3194
+ var DESIGNATORS = {
3195
+ apt: "Apt",
3196
+ apartment: "Apt",
3197
+ unit: "Unit",
3198
+ ste: "Ste",
3199
+ suite: "Ste",
3200
+ bldg: "Bldg",
3201
+ building: "Bldg",
3202
+ fl: "Fl",
3203
+ floor: "Fl",
3204
+ rm: "Rm",
3205
+ room: "Rm",
3206
+ spc: "Spc",
3207
+ space: "Spc",
3208
+ lot: "Lot",
3209
+ trlr: "Trlr",
3210
+ "#": "#"
3211
+ };
3212
+ var UNIT_AT_END = /[\s,]+(#|apt|apartment|unit|ste|suite|bldg|building|fl|floor|rm|room|spc|space|lot|trlr)\.?\s*#?\s*([A-Za-z0-9-]+)$/i;
3213
+ var UNIT_ONLY = /^(#|apt|apartment|unit|ste|suite|bldg|building|fl|floor|rm|room|spc|space|lot|trlr)?\.?\s*#?\s*([A-Za-z0-9-]+)$/i;
3214
+ var STREET_NUMBER2 = /^([A-Za-z]?\d+[A-Za-z]?(?:-\d+)?)\s+(.+)$/;
3215
+ var unitText = (unit) => unit.designator === "#" ? `#${unit.value}` : `${unit.designator} ${unit.value}`;
3216
+ var parseUnit = (designator, value) => ({
3217
+ designator: DESIGNATORS[(designator ?? "#").toLowerCase()] ?? "#",
3218
+ value: value.toUpperCase()
3219
+ });
3220
+ var splitUnit = (line) => {
3221
+ const match = UNIT_AT_END.exec(line);
3222
+ if (!match || match.index === 0) return { street: line.trim(), unit: void 0 };
3223
+ return {
3224
+ street: line.slice(0, match.index).trim(),
3225
+ unit: parseUnit(match[1], match[2])
3226
+ };
3227
+ };
3228
+ var streetKey = (street) => normalize(street).split(" ").map((word) => (ABBREVIATIONS[word] ?? word).toLowerCase()).join(" ");
3229
+ var standardizeStreet = (street) => street.replace(/[.,]/g, " ").split(/\s+/).filter(Boolean).map((word) => {
3230
+ const lower = word.toLowerCase();
3231
+ if (DIRECTIONALS.has(lower)) return lower.toUpperCase();
3232
+ return ABBREVIATIONS[lower] ?? word;
3233
+ }).join(" ");
3234
+ var stateCode = (value) => {
3235
+ if (!value) return void 0;
3236
+ const upper = value.trim().toUpperCase();
3237
+ if (STATE_NAMES[upper]) return upper;
3238
+ const byName = Object.entries(STATE_NAMES).find(([, name]) => name.toUpperCase() === upper);
3239
+ return byName?.[0] ?? upper;
3240
+ };
3241
+ var cityRows = (rows, city, state) => rows.filter(
3242
+ (row2) => normalize(row2.city) === normalize(city) && (state === void 0 || row2.state === state)
3243
+ );
3244
+ var resolve = (input, rows) => {
3245
+ const [first = "", ...rest] = input.addressLines;
3246
+ let streetLine = first;
3247
+ let unit;
3248
+ let locality = input.locality;
3249
+ let state = stateCode(input.administrativeArea);
3250
+ let zip = input.postalCode?.slice(0, 5);
3251
+ let candidates = [];
3252
+ if (locality || zip) {
3253
+ const second = rest.join(" ").trim();
3254
+ if (second) {
3255
+ const only = UNIT_ONLY.exec(second);
3256
+ if (only) unit = parseUnit(only[1], only[2]);
3257
+ }
3258
+ } else {
3259
+ const joined = input.addressLines.join(", ");
3260
+ const parsed = parseStreetInCity(joined, rows);
3261
+ if (parsed) {
3262
+ streetLine = parsed.line1;
3263
+ locality = parsed.row.city;
3264
+ state = parsed.row.state;
3265
+ const zipMatch = /\b(\d{5})(?:-\d{4})?\s*(?:,?\s*(?:USA|US|United States))?$/i.exec(joined);
3266
+ zip = zipMatch?.[1];
3267
+ }
3268
+ }
3269
+ const split = splitUnit(streetLine);
3270
+ const street = split.street;
3271
+ unit = unit ?? split.unit;
3272
+ const numbered = STREET_NUMBER2.exec(street);
3273
+ if (locality) candidates = cityRows(rows, locality, state);
3274
+ let localityStatus = "confirmed";
3275
+ let stateStatus = "confirmed";
3276
+ if (candidates.length === 0 && zip) {
3277
+ candidates = rows.filter((row2) => row2.zip === zip);
3278
+ if (candidates.length > 0) {
3279
+ localityStatus = "replaced";
3280
+ if (state !== void 0 && candidates[0]?.state !== state) stateStatus = "replaced";
3281
+ }
3282
+ }
3283
+ if (candidates.length === 0 || !numbered) {
3284
+ return { unresolved: { street, unit, hasNumber: !!numbered } };
3285
+ }
3286
+ const number = numbered[1];
3287
+ const key = streetKey(street);
3288
+ const exact = candidates.find((row2) => streetKey(row2.line1) === key);
3289
+ const base = exact ?? candidates.find((row2) => zip !== void 0 && row2.zip === zip) ?? candidates[0];
3290
+ const outStreet = exact ? exact.line1 : standardizeStreet(street);
3291
+ const routeMatch = STREET_NUMBER2.exec(outStreet);
3292
+ return {
3293
+ resolved: {
3294
+ row: base,
3295
+ street: outStreet,
3296
+ number,
3297
+ route: routeMatch ? routeMatch[2] : outStreet,
3298
+ unit,
3299
+ inCorpus: !!exact,
3300
+ postal: zip === void 0 ? "inferred" : zip === base.zip ? "confirmed" : "replaced",
3301
+ locality: localityStatus,
3302
+ state: stateStatus
3303
+ }
3304
+ };
3305
+ };
3306
+ var fnv = (value, seed = 2166136261) => {
3307
+ let hash = seed >>> 0;
3308
+ for (let i = 0; i < value.length; i++) {
3309
+ hash ^= value.charCodeAt(i);
3310
+ hash = Math.imul(hash, 16777619) >>> 0;
3311
+ }
3312
+ return hash;
3313
+ };
3314
+ var zipPlus4 = (row2, street) => String(fnv(`${row2.id}|${streetKey(street)}`) % 9999 + 1).padStart(4, "0");
3315
+ var responseId = (seed) => {
3316
+ const hex = [2166136261, 16777619, 2654435769, 2135587861].map((s) => fnv(seed, s).toString(16).padStart(8, "0")).join("");
3317
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-4${hex.slice(13, 16)}-a${hex.slice(17, 20)}-${hex.slice(20, 32)}`;
3318
+ };
3319
+ var component = (text2, componentType, confirmationLevel, flags = {}) => ({
3320
+ componentName: { text: text2, languageCode: "en" },
3321
+ componentType,
3322
+ confirmationLevel,
3323
+ ...flags.inferred ? { inferred: true } : {},
3324
+ ...flags.replaced ? { replaced: true } : {}
3325
+ });
3326
+ var compact = (value) => Object.fromEntries(
3327
+ Object.entries(value).filter(
3328
+ ([, v]) => v !== void 0 && v !== false && !(Array.isArray(v) && v.length === 0)
3329
+ )
3330
+ );
3331
+ var uniq = (values) => [...new Set(values)];
3332
+ var validateAddress = (request, rows, options = {}) => {
3333
+ const { address: input, enableUspsCass } = request;
3334
+ const region = input.regionCode ?? "US";
3335
+ const usps = region === "US" || region === "PR";
3336
+ const outcome = region === "US" ? resolve(input, rows) : void 0;
3337
+ let granularity;
3338
+ let inputGranularity;
3339
+ let addressComplete;
3340
+ let nextAction;
3341
+ let dpv;
3342
+ let dpvFootnote;
3343
+ let unconfirmed = [];
3344
+ let missing = [];
3345
+ let hasReplaced = false;
3346
+ let hasInferred = false;
3347
+ let uspsError;
3348
+ const components = [];
3349
+ let postalAddress;
3350
+ let formattedAddress2;
3351
+ let geocode2;
3352
+ let standardized;
3353
+ let rowId;
3354
+ if (!outcome || "unresolved" in outcome) {
3355
+ const street = outcome && "unresolved" in outcome ? outcome.unresolved : void 0;
3356
+ const hasNumber = street?.hasNumber ?? STREET_NUMBER2.test(input.addressLines[0] ?? "");
3357
+ const unit = street?.unit;
3358
+ const cityKnown = input.locality !== void 0 && cityRows(rows, input.locality, stateCode(input.administrativeArea)).length > 0;
3359
+ inputGranularity = unit ? "SUB_PREMISE" : hasNumber ? "PREMISE" : "ROUTE";
3360
+ addressComplete = false;
3361
+ nextAction = "FIX";
3362
+ if (cityKnown && !hasNumber) {
3363
+ granularity = "ROUTE";
3364
+ missing = ["street_number"];
3365
+ dpv = void 0;
3366
+ } else {
3367
+ granularity = "OTHER";
3368
+ dpv = usps ? "N" : void 0;
3369
+ }
3370
+ const streetText = street?.street ?? input.addressLines[0] ?? "";
3371
+ const split = STREET_NUMBER2.exec(streetText);
3372
+ const routeLevel = cityKnown ? "UNCONFIRMED_BUT_PLAUSIBLE" : "UNCONFIRMED_AND_SUSPICIOUS";
3373
+ if (split) {
3374
+ components.push(component(split[1], "street_number", routeLevel));
3375
+ components.push(component(split[2], "route", routeLevel));
3376
+ } else if (streetText) {
3377
+ components.push(
3378
+ component(streetText, "route", cityKnown ? "CONFIRMED" : "UNCONFIRMED_AND_SUSPICIOUS")
3379
+ );
3380
+ }
3381
+ if (unit) components.push(component(unitText(unit), "subpremise", routeLevel));
3382
+ if (input.locality) {
3383
+ components.push(
3384
+ component(
3385
+ input.locality,
3386
+ "locality",
3387
+ cityKnown ? "CONFIRMED" : "UNCONFIRMED_AND_SUSPICIOUS"
3388
+ )
3389
+ );
3390
+ }
3391
+ const state = stateCode(input.administrativeArea);
3392
+ if (state) {
3393
+ components.push(
3394
+ component(
3395
+ state,
3396
+ "administrative_area_level_1",
3397
+ STATE_NAMES[state] ? "CONFIRMED" : "UNCONFIRMED_AND_SUSPICIOUS"
3398
+ )
3399
+ );
3400
+ }
3401
+ if (input.postalCode) {
3402
+ const zipKnown = rows.some((row2) => row2.zip === input.postalCode?.slice(0, 5));
3403
+ components.push(
3404
+ component(
3405
+ input.postalCode,
3406
+ "postal_code",
3407
+ zipKnown ? "CONFIRMED" : "UNCONFIRMED_AND_SUSPICIOUS"
3408
+ )
3409
+ );
3410
+ }
3411
+ components.push(
3412
+ component(region === "US" ? "USA" : region, "country", "CONFIRMED", {
3413
+ inferred: input.regionCode === void 0
3414
+ })
3415
+ );
3416
+ hasInferred = input.regionCode === void 0;
3417
+ unconfirmed = components.filter((c) => c.confirmationLevel !== "CONFIRMED").map((c) => c.componentType);
3418
+ const line = [streetText, unit ? unitText(unit) : ""].filter(Boolean).join(" ");
3419
+ postalAddress = compact({
3420
+ regionCode: region,
3421
+ languageCode: "en",
3422
+ postalCode: input.postalCode,
3423
+ administrativeArea: state,
3424
+ locality: input.locality,
3425
+ addressLines: line ? [line] : void 0
3426
+ });
3427
+ formattedAddress2 = [
3428
+ line,
3429
+ input.locality,
3430
+ [state, input.postalCode].filter(Boolean).join(" "),
3431
+ region === "US" ? "USA" : region
3432
+ ].filter(Boolean).join(", ");
3433
+ } else {
3434
+ const r = outcome.resolved;
3435
+ const row2 = r.row;
3436
+ rowId = row2.id;
3437
+ const street = r.street;
3438
+ const validation = row2.validation ?? {};
3439
+ const plus4 = zipPlus4(row2, street);
3440
+ inputGranularity = r.unit ? "SUB_PREMISE" : "PREMISE";
3441
+ granularity = "PREMISE";
3442
+ addressComplete = true;
3443
+ nextAction = "ACCEPT";
3444
+ dpv = "Y";
3445
+ dpvFootnote = "AABB";
3446
+ let unitLevel = "CONFIRMED";
3447
+ if (validation.multiUnit) {
3448
+ if (!r.unit) {
3449
+ missing = ["subpremise"];
3450
+ addressComplete = false;
3451
+ nextAction = "CONFIRM_ADD_SUBPREMISES";
3452
+ dpv = "D";
3453
+ dpvFootnote = "AAN1";
3454
+ } else if (validation.units === void 0 || validation.units.some((u) => u.toUpperCase() === r.unit?.value)) {
3455
+ granularity = "SUB_PREMISE";
3456
+ } else {
3457
+ unitLevel = "UNCONFIRMED_BUT_PLAUSIBLE";
3458
+ nextAction = "CONFIRM";
3459
+ dpv = "S";
3460
+ dpvFootnote = "AACC";
3461
+ }
3462
+ } else if (r.unit) {
3463
+ unitLevel = "UNCONFIRMED_BUT_PLAUSIBLE";
3464
+ nextAction = "CONFIRM";
3465
+ dpvFootnote = "AACC";
3466
+ }
3467
+ if (r.postal === "replaced" || r.locality === "replaced" || r.state === "replaced") {
3468
+ hasReplaced = true;
3469
+ if (nextAction === "ACCEPT") nextAction = "CONFIRM";
3470
+ }
3471
+ components.push(component(r.number, "street_number", "CONFIRMED"));
3472
+ components.push(component(r.route, "route", "CONFIRMED"));
3473
+ if (r.unit) components.push(component(unitText(r.unit), "subpremise", unitLevel));
3474
+ components.push(
3475
+ component(row2.city, "locality", "CONFIRMED", { replaced: r.locality === "replaced" })
3476
+ );
3477
+ components.push(
3478
+ component(row2.state, "administrative_area_level_1", "CONFIRMED", {
3479
+ replaced: r.state === "replaced"
3480
+ })
3481
+ );
3482
+ components.push(
3483
+ component(row2.zip, "postal_code", "CONFIRMED", {
3484
+ inferred: r.postal === "inferred",
3485
+ replaced: r.postal === "replaced"
3486
+ })
3487
+ );
3488
+ components.push(component(plus4, "postal_code_suffix", "CONFIRMED", { inferred: true }));
3489
+ components.push(
3490
+ component("USA", "country", "CONFIRMED", { inferred: input.regionCode === void 0 })
3491
+ );
3492
+ hasInferred = true;
3493
+ unconfirmed = components.filter((c) => c.confirmationLevel !== "CONFIRMED").map((c) => c.componentType);
3494
+ if (validation.granularity) granularity = validation.granularity;
3495
+ if (validation.addressComplete !== void 0) addressComplete = validation.addressComplete;
3496
+ if (validation.possibleNextAction) nextAction = validation.possibleNextAction;
3497
+ if (validation.dpvConfirmation) dpv = validation.dpvConfirmation;
3498
+ if (validation.unconfirmedComponentTypes)
3499
+ unconfirmed = [...validation.unconfirmedComponentTypes];
3500
+ if (validation.uspsErrorMessage) uspsError = validation.uspsErrorMessage;
3501
+ const line = [street, r.unit ? unitText(r.unit) : ""].filter(Boolean).join(" ");
3502
+ const zip = `${row2.zip}-${plus4}`;
3503
+ postalAddress = {
3504
+ regionCode: "US",
3505
+ languageCode: "en",
3506
+ postalCode: zip,
3507
+ administrativeArea: row2.state,
3508
+ locality: row2.city,
3509
+ addressLines: [line]
3510
+ };
3511
+ formattedAddress2 = `${line}, ${row2.city}, ${row2.state} ${zip}, USA`;
3512
+ const place = r.inCorpus ? { placeId: corpusPlaceId(row2), lat: row2.lat, lng: row2.lng } : synthesize(street, row2);
3513
+ geocode2 = {
3514
+ location: { latitude: place.lat, longitude: place.lng },
3515
+ placeId: place.placeId,
3516
+ placeTypes: r.unit ? ["subpremise"] : ["premise"]
3517
+ };
3518
+ standardized = {
3519
+ firstAddressLine: line.toUpperCase(),
3520
+ cityStateZipAddressLine: `${row2.city.toUpperCase()} ${row2.state} ${zip}`,
3521
+ city: row2.city.toUpperCase(),
3522
+ state: row2.state,
3523
+ zipCode: row2.zip,
3524
+ zipCodeExtension: plus4
3525
+ };
3526
+ }
3527
+ if (options.dpvOverride) dpv = options.dpvOverride;
3528
+ if (dpv === "N") standardized = void 0;
3529
+ if (dpv !== void 0 && dpvFootnote === void 0) dpvFootnote = dpv === "N" ? "A1M1" : "AABB";
3530
+ if (dpv === "N") dpvFootnote = "A1M1";
3531
+ const verdict = compact({
3532
+ inputGranularity,
3533
+ validationGranularity: granularity,
3534
+ geocodeGranularity: granularity === "SUB_PREMISE" ? "PREMISE" : granularity,
3535
+ addressComplete,
3536
+ hasUnconfirmedComponents: unconfirmed.length > 0,
3537
+ hasInferredComponents: hasInferred,
3538
+ hasReplacedComponents: hasReplaced,
3539
+ possibleNextAction: nextAction
3540
+ });
3541
+ const address = compact({
3542
+ formattedAddress: formattedAddress2,
3543
+ postalAddress,
3544
+ addressComponents: components,
3545
+ missingComponentTypes: uniq(missing),
3546
+ unconfirmedComponentTypes: uniq(unconfirmed)
3547
+ });
3548
+ const uspsData = usps ? uspsError ? compact({ errorMessage: uspsError, cassProcessed: enableUspsCass }) : compact({
3549
+ standardizedAddress: standardized,
3550
+ dpvConfirmation: dpv,
3551
+ dpvFootnote: dpv ? dpvFootnote : void 0,
3552
+ postOfficeCity: standardized ? standardized.city : void 0,
3553
+ postOfficeState: standardized ? standardized.state : void 0,
3554
+ cassProcessed: enableUspsCass
3555
+ }) : void 0;
3556
+ const result = compact({ verdict, address, geocode: geocode2, uspsData });
3557
+ const verdictClass = `${nextAction}/${uspsError ? "ERROR" : dpv ?? "-"}`;
3558
+ return {
3559
+ body: { result, responseId: responseId(JSON.stringify({ input, enableUspsCass })) },
3560
+ rowId,
3561
+ verdictClass
3562
+ };
3563
+ };
3564
+
3013
3565
  // src/runtime.ts
3014
3566
  var WEB_SERVICES = ["PlaceAutocomplete", "PlaceDetails", "Geocode", "FindPlaceFromText"];
3015
3567
  var everyWebService = (rule) => WEB_SERVICES.map((operationId) => ({ operationId, ...rule }));
@@ -3054,6 +3606,60 @@ var GOOGLE_MAPS_PRESETS = {
3054
3606
  description: "Every web-service call is held 6 s: past QA's 5 s wait for predictions",
3055
3607
  rules: everyWebService({ latencyMs: 6e3 })
3056
3608
  },
3609
+ address_validation_denied: {
3610
+ description: "Address Validation answers 403 PERMISSION_DENIED, as for a key without the API enabled",
3611
+ rules: [
3612
+ {
3613
+ operationId: "ValidateAddress",
3614
+ status: 403,
3615
+ body: {
3616
+ error: {
3617
+ code: 403,
3618
+ message: "Requests to this API addressvalidation.googleapis.com method google.maps.addressvalidation.v1.AddressValidation.ValidateAddress are blocked.",
3619
+ status: "PERMISSION_DENIED",
3620
+ details: [
3621
+ {
3622
+ "@type": "type.googleapis.com/google.rpc.ErrorInfo",
3623
+ reason: "API_KEY_SERVICE_BLOCKED",
3624
+ domain: "googleapis.com",
3625
+ metadata: { service: "addressvalidation.googleapis.com" }
3626
+ }
3627
+ ]
3628
+ }
3629
+ }
3630
+ }
3631
+ ]
3632
+ },
3633
+ address_validation_unavailable: {
3634
+ description: "Address Validation answers 503 UNAVAILABLE (Google's transient failure)",
3635
+ rules: [
3636
+ {
3637
+ operationId: "ValidateAddress",
3638
+ status: 503,
3639
+ body: {
3640
+ error: {
3641
+ code: 503,
3642
+ message: "The service is currently unavailable.",
3643
+ status: "UNAVAILABLE"
3644
+ }
3645
+ }
3646
+ }
3647
+ ]
3648
+ },
3649
+ address_validation_slow: {
3650
+ description: "Address Validation is held 3 s: past a 2.5 s checkout timeout",
3651
+ rules: [{ operationId: "ValidateAddress", latencyMs: 3e3 }]
3652
+ },
3653
+ address_validation_no_verdict: {
3654
+ description: `Address Validation answers 200 {"result": {}} (no verdict): a malformed answer, for a client's defensive branch`,
3655
+ rules: [{ operationId: "ValidateAddress", status: 200, body: { result: {} } }]
3656
+ },
3657
+ address_validation_dpv_n: {
3658
+ description: "Address Validation reports USPS DPV confirmation N (not deliverable)",
3659
+ rules: [
3660
+ { operationId: "ValidateAddress", effect: "usps_dpv", params: { dpvConfirmation: "N" } }
3661
+ ]
3662
+ },
3057
3663
  script_unavailable: {
3058
3664
  description: "The Maps JavaScript API answers 503, so the script's onerror fires",
3059
3665
  rules: [{ operationId: "MapsJavaScriptApi", status: 503, body: "Service Unavailable" }]
@@ -3061,9 +3667,46 @@ var GOOGLE_MAPS_PRESETS = {
3061
3667
  };
3062
3668
  var json3 = (status, body) => new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json" } });
3063
3669
  var adminError3 = (status, message) => json3(status, { error: { type: "mockingbird_admin", message } });
3064
- var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
3670
+ var isRecord5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
3671
+ var stringList = (value) => Array.isArray(value) && value.every((v) => typeof v === "string") ? value : void 0;
3672
+ var parseValidation = (value, index) => {
3673
+ if (value === void 0 || value === null) return void 0;
3674
+ const at = `addresses[${index}].validation`;
3675
+ if (!isRecord5(value)) return `${at} must be an object`;
3676
+ const out = {};
3677
+ const enums = [
3678
+ ["granularity", GRANULARITIES],
3679
+ ["possibleNextAction", NEXT_ACTIONS],
3680
+ ["dpvConfirmation", DPV_CODES]
3681
+ ];
3682
+ for (const [key, allowed] of enums) {
3683
+ if (value[key] === void 0) continue;
3684
+ if (!allowed.includes(value[key])) {
3685
+ return `${at}.${key} must be one of ${allowed.join(", ")}`;
3686
+ }
3687
+ Object.assign(out, { [key]: value[key] });
3688
+ }
3689
+ for (const key of ["addressComplete", "multiUnit"]) {
3690
+ if (value[key] === void 0) continue;
3691
+ if (typeof value[key] !== "boolean") return `${at}.${key} must be a boolean`;
3692
+ out[key] = value[key];
3693
+ }
3694
+ for (const key of ["unconfirmedComponentTypes", "units"]) {
3695
+ if (value[key] === void 0) continue;
3696
+ const list = stringList(value[key]);
3697
+ if (!list) return `${at}.${key} must be a string[]`;
3698
+ out[key] = list;
3699
+ }
3700
+ if (value.uspsErrorMessage !== void 0) {
3701
+ if (typeof value.uspsErrorMessage !== "string" || !value.uspsErrorMessage) {
3702
+ return `${at}.uspsErrorMessage must be a non-empty string`;
3703
+ }
3704
+ out.uspsErrorMessage = value.uspsErrorMessage;
3705
+ }
3706
+ return out;
3707
+ };
3065
3708
  var parseAddress = (value, index) => {
3066
- if (!isRecord4(value)) return `addresses[${index}] must be an object`;
3709
+ if (!isRecord5(value)) return `addresses[${index}] must be an object`;
3067
3710
  for (const key of ["line1", "city", "state", "zip"]) {
3068
3711
  if (typeof value[key] !== "string" || !value[key].trim()) {
3069
3712
  return `addresses[${index}].${key} must be a non-empty string`;
@@ -3071,6 +3714,8 @@ var parseAddress = (value, index) => {
3071
3714
  }
3072
3715
  const state = String(value.state).toUpperCase();
3073
3716
  if (!/^[A-Z]{2}$/.test(state)) return `addresses[${index}].state must be a two-letter code`;
3717
+ const validation = parseValidation(value.validation, index);
3718
+ if (typeof validation === "string") return validation;
3074
3719
  const lat = value.lat === void 0 ? 0 : Number(value.lat);
3075
3720
  const lng = value.lng === void 0 ? 0 : Number(value.lng);
3076
3721
  if (!Number.isFinite(lat) || !Number.isFinite(lng)) {
@@ -3084,7 +3729,8 @@ var parseAddress = (value, index) => {
3084
3729
  zip: String(value.zip).trim(),
3085
3730
  county: typeof value.county === "string" ? value.county : "",
3086
3731
  lat,
3087
- lng
3732
+ lng,
3733
+ ...validation ? { validation } : {}
3088
3734
  };
3089
3735
  };
3090
3736
  var adminRoutes = (runtime) => ({
@@ -3096,9 +3742,12 @@ var adminRoutes = (runtime) => ({
3096
3742
  });
3097
3743
  },
3098
3744
  "PUT /corpus": ({ body, namespace }) => {
3099
- const list = Array.isArray(body) ? body : isRecord4(body) ? body.addresses : void 0;
3745
+ const list = Array.isArray(body) ? body : isRecord5(body) ? body.addresses : void 0;
3100
3746
  if (!Array.isArray(list)) {
3101
- return adminError3(400, 'expected {"addresses": [{line1, city, state, zip, lat?, lng?}]}');
3747
+ return adminError3(
3748
+ 400,
3749
+ 'expected {"addresses": [{line1, city, state, zip, lat?, lng?, validation?}]}'
3750
+ );
3102
3751
  }
3103
3752
  const rows = [];
3104
3753
  for (const [index, each] of list.entries()) {
@@ -3116,7 +3765,7 @@ var adminRoutes = (runtime) => ({
3116
3765
  },
3117
3766
  "GET /settings": ({ namespace }) => json3(200, runtime.instance(namespace).state.current()),
3118
3767
  "PUT /settings": ({ body, namespace }) => {
3119
- if (!isRecord4(body)) return adminError3(400, "expected a JSON object");
3768
+ if (!isRecord5(body)) return adminError3(400, "expected a JSON object");
3120
3769
  const patch = {};
3121
3770
  if (body.keys !== void 0) {
3122
3771
  if (!Array.isArray(body.keys)) return adminError3(400, "keys: string[]");
@@ -3159,7 +3808,9 @@ var createRuntime2 = (options = {}) => createRuntime({
3159
3808
  var GOOGLE_MAPS_NAMESPACE = "google-maps";
3160
3809
  var MISSING_KEY_MESSAGE = "You must use an API key to authenticate each request to Google Maps Platform APIs. For additional information, please refer to http://g.co/dev/maps-no-account";
3161
3810
  var INVALID_KEY_MESSAGE = "The provided API key is invalid. ";
3162
- var keyCredential = (request) => new URL(request.url).searchParams.get("key") ?? void 0;
3811
+ var MISSING_API_KEY_MESSAGE = "The request is missing a valid API key.";
3812
+ var INVALID_API_KEY_MESSAGE = "API key not valid. Please pass a valid API key.";
3813
+ var keyCredential = (request) => new URL(request.url).searchParams.get("key") ?? request.headers.get("x-goog-api-key") ?? void 0;
3163
3814
  var CORS = { "access-control-allow-origin": "*" };
3164
3815
  var json4 = (body, status = 200) => new Response(JSON.stringify(body, null, 3), {
3165
3816
  status,
@@ -3176,6 +3827,17 @@ var DEFAULT_MESSAGES = {
3176
3827
  UNKNOWN_ERROR: "An unknown error occurred. Please try again.",
3177
3828
  REQUEST_DENIED: INVALID_KEY_MESSAGE
3178
3829
  };
3830
+ var apiError = (error) => json4({ error }, error.code);
3831
+ var requestJson = (body) => {
3832
+ if (body.kind === "json") return body.value;
3833
+ if (body.kind === "empty") return {};
3834
+ const raw = body.kind === "bytes" ? new TextDecoder().decode(body.value) : body.kind === "text" ? body.value : body.kind === "invalid" ? body.text : void 0;
3835
+ try {
3836
+ return JSON.parse(raw ?? "");
3837
+ } catch {
3838
+ throw new ValidationRequestError("Invalid JSON payload received.");
3839
+ }
3840
+ };
3179
3841
  var text = (value) => typeof value === "string" ? value : Array.isArray(value) ? String(value[0]) : void 0;
3180
3842
  var GoogleMapsAPI = class {
3181
3843
  app;
@@ -3196,7 +3858,8 @@ var GoogleMapsAPI = class {
3196
3858
  PlaceDetails: (context) => this.details(context),
3197
3859
  Geocode: (context) => this.geocode(context),
3198
3860
  FindPlaceFromText: (context) => this.findPlace(context),
3199
- MapsJavaScriptApi: (context) => this.script(context)
3861
+ MapsJavaScriptApi: (context) => this.script(context),
3862
+ ValidateAddress: (context) => this.validate(context)
3200
3863
  });
3201
3864
  this.service = createService({
3202
3865
  document,
@@ -3239,6 +3902,7 @@ var GoogleMapsAPI = class {
3239
3902
  gate(context) {
3240
3903
  const operationId = context.operation.operationId;
3241
3904
  if (operationId === "MapsJavaScriptApi") return void 0;
3905
+ if (operationId === "ValidateAddress") return this.cloudGate(context);
3242
3906
  const key = text(context.query.key);
3243
3907
  if (!key) return this.status(operationId, "REQUEST_DENIED", MISSING_KEY_MESSAGE);
3244
3908
  const keys = this.state.current().keys;
@@ -3253,6 +3917,50 @@ var GoogleMapsAPI = class {
3253
3917
  }
3254
3918
  return void 0;
3255
3919
  }
3920
+ /** Key check for the Google Cloud-style Address Validation API. */
3921
+ cloudGate(context) {
3922
+ const key = text(context.query.key) ?? context.request.headers.get("x-goog-api-key");
3923
+ if (!key) {
3924
+ return apiError({ code: 403, message: MISSING_API_KEY_MESSAGE, status: "PERMISSION_DENIED" });
3925
+ }
3926
+ const keys = this.state.current().keys;
3927
+ if (keys.length > 0 && !keys.includes(key)) {
3928
+ return apiError({
3929
+ code: 400,
3930
+ message: INVALID_API_KEY_MESSAGE,
3931
+ status: "INVALID_ARGUMENT",
3932
+ details: [
3933
+ {
3934
+ "@type": "type.googleapis.com/google.rpc.ErrorInfo",
3935
+ reason: "API_KEY_INVALID",
3936
+ domain: "googleapis.com",
3937
+ metadata: { service: "addressvalidation.googleapis.com" }
3938
+ }
3939
+ ]
3940
+ });
3941
+ }
3942
+ return void 0;
3943
+ }
3944
+ validate(context) {
3945
+ let request;
3946
+ try {
3947
+ request = parseValidateRequest(requestJson(context.body));
3948
+ } catch (error) {
3949
+ if (!(error instanceof ValidationRequestError)) throw error;
3950
+ return apiError({ code: 400, message: error.message, status: "INVALID_ARGUMENT" });
3951
+ }
3952
+ const forced = faultEffect(context.request, "usps_dpv")?.dpvConfirmation;
3953
+ const dpvOverride = DPV_CODES.includes(forced) ? forced : void 0;
3954
+ const outcome = validateAddress(request, this.state.corpus(), {
3955
+ ...dpvOverride ? { dpvOverride } : {}
3956
+ });
3957
+ return annotateResponse(json4(outcome.body), {
3958
+ ids: {
3959
+ ...outcome.rowId ? { addressRowId: outcome.rowId } : {},
3960
+ verdict: outcome.verdictClass
3961
+ }
3962
+ });
3963
+ }
3256
3964
  noted(response, context, place) {
3257
3965
  const session = text(context.query.sessiontoken);
3258
3966
  const ids = {};
@@ -3387,7 +4095,9 @@ export {
3387
4095
  GOOGLE_MAPS_NAMESPACE,
3388
4096
  MISSING_KEY_MESSAGE,
3389
4097
  INVALID_KEY_MESSAGE,
4098
+ MISSING_API_KEY_MESSAGE,
4099
+ INVALID_API_KEY_MESSAGE,
3390
4100
  keyCredential,
3391
4101
  GoogleMapsAPI
3392
4102
  };
3393
- //# sourceMappingURL=chunk-5HEE5U7V.js.map
4103
+ //# sourceMappingURL=chunk-G5DEDMPE.js.map