@crvouga/mockingbird-service-google-maps 0.2.0 → 1.1.0

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) {
@@ -1273,7 +1273,7 @@ var restoreNamespace = (sqlite, namespace, snapshot) => {
1273
1273
  };
1274
1274
 
1275
1275
  // ../core/dist/version.js
1276
- var PACKAGE_VERSION = true ? "0.2.0" : UNRELEASED_VERSION;
1276
+ var PACKAGE_VERSION = true ? "1.1.0" : UNRELEASED_VERSION;
1277
1277
 
1278
1278
  // ../core/dist/signing.js
1279
1279
  var encoder = new TextEncoder();
@@ -1441,7 +1441,7 @@ var createRuntime = (options) => {
1441
1441
  const rng = createRng(options.seed ?? 0);
1442
1442
  const wallNow = options.io?.wallNow ?? Date.now;
1443
1443
  const monotonicNow = options.io?.monotonicNow ?? (() => performance.now());
1444
- const sleep = options.io?.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
1444
+ const sleep = options.io?.sleep ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
1445
1445
  const faults = createFaultRegistry(createRng(options.seed ?? 0), sleep);
1446
1446
  const metrics = createMetrics();
1447
1447
  const journal = createJournal(options.journalSize ?? DEFAULT_JOURNAL_SIZE);
@@ -1945,9 +1945,9 @@ var presetRoutes = (presets, runtime) => ({
1945
1945
  });
1946
1946
 
1947
1947
  // 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"];
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"}}}}}}},"/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"}}}}}}`);
1949
+ var operationIds = ["PlaceAutocomplete", "PlaceDetails", "Geocode", "FindPlaceFromText", "MapsJavaScriptApi", "ValidateAddress"];
1950
+ var supportedOperationIds = ["PlaceAutocomplete", "PlaceDetails", "Geocode", "FindPlaceFromText", "MapsJavaScriptApi", "ValidateAddress"];
1951
1951
 
1952
1952
  // src/corpus.ts
1953
1953
  var row = (id, line1, city, state, zip, county, lat, lng) => ({ id, line1, city, state, zip, county, lat, lng });
@@ -3010,6 +3010,528 @@ var GoogleMapsState = class {
3010
3010
  }
3011
3011
  };
3012
3012
 
3013
+ // src/validation.ts
3014
+ var GRANULARITIES = [
3015
+ "SUB_PREMISE",
3016
+ "PREMISE",
3017
+ "PREMISE_PROXIMITY",
3018
+ "BLOCK",
3019
+ "ROUTE",
3020
+ "OTHER"
3021
+ ];
3022
+ var NEXT_ACTIONS = [
3023
+ "FIX",
3024
+ "CONFIRM_ADD_SUBPREMISES",
3025
+ "CONFIRM",
3026
+ "ACCEPT"
3027
+ ];
3028
+ var DPV_CODES = ["Y", "N", "S", "D"];
3029
+ var ValidationRequestError = class extends Error {
3030
+ constructor(message) {
3031
+ super(message);
3032
+ this.name = "ValidationRequestError";
3033
+ }
3034
+ };
3035
+ var TOP_LEVEL = /* @__PURE__ */ new Set([
3036
+ "address",
3037
+ "previousResponseId",
3038
+ "enableUspsCass",
3039
+ "languageOptions",
3040
+ "sessionToken"
3041
+ ]);
3042
+ var POSTAL_ADDRESS = /* @__PURE__ */ new Set([
3043
+ "revision",
3044
+ "regionCode",
3045
+ "languageCode",
3046
+ "postalCode",
3047
+ "sortingCode",
3048
+ "administrativeArea",
3049
+ "locality",
3050
+ "sublocality",
3051
+ "addressLines",
3052
+ "recipients",
3053
+ "organization"
3054
+ ]);
3055
+ var MAX_INPUT_LENGTH = 280;
3056
+ var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
3057
+ var optionalString = (value, field) => {
3058
+ if (value === void 0 || value === null) return void 0;
3059
+ if (typeof value !== "string") {
3060
+ throw new ValidationRequestError(
3061
+ `Invalid value at '${field}' (TYPE_STRING), ${JSON.stringify(value)}`
3062
+ );
3063
+ }
3064
+ const trimmed = value.trim();
3065
+ return trimmed ? trimmed : void 0;
3066
+ };
3067
+ var parseValidateRequest = (body) => {
3068
+ if (!isRecord4(body)) throw new ValidationRequestError("Invalid JSON payload received.");
3069
+ for (const key of Object.keys(body)) {
3070
+ if (!TOP_LEVEL.has(key)) {
3071
+ throw new ValidationRequestError(
3072
+ `Invalid JSON payload received. Unknown name "${key}": Cannot find field.`
3073
+ );
3074
+ }
3075
+ }
3076
+ const address = body.address;
3077
+ if (address === void 0 || address === null) {
3078
+ throw new ValidationRequestError("Address is missing from the request.");
3079
+ }
3080
+ if (!isRecord4(address)) {
3081
+ throw new ValidationRequestError(
3082
+ `Invalid value at 'address' (type.googleapis.com/google.type.PostalAddress), ${JSON.stringify(address)}`
3083
+ );
3084
+ }
3085
+ for (const key of Object.keys(address)) {
3086
+ if (!POSTAL_ADDRESS.has(key)) {
3087
+ throw new ValidationRequestError(
3088
+ `Invalid JSON payload received. Unknown name "${key}" at 'address': Cannot find field.`
3089
+ );
3090
+ }
3091
+ }
3092
+ const rawLines = address.addressLines ?? [];
3093
+ if (!Array.isArray(rawLines) || rawLines.some((line) => typeof line !== "string")) {
3094
+ throw new ValidationRequestError(
3095
+ `Invalid value at 'address.address_lines' (TYPE_STRING), ${JSON.stringify(rawLines)}`
3096
+ );
3097
+ }
3098
+ const addressLines = rawLines.map((line) => line.trim()).filter(Boolean);
3099
+ if (addressLines.length === 0) {
3100
+ throw new ValidationRequestError("Address lines are missing from the request.");
3101
+ }
3102
+ const enable = body.enableUspsCass;
3103
+ if (enable !== void 0 && enable !== null && typeof enable !== "boolean") {
3104
+ throw new ValidationRequestError(
3105
+ `Invalid value at 'enable_usps_cass' (TYPE_BOOL), ${JSON.stringify(enable)}`
3106
+ );
3107
+ }
3108
+ const input = {
3109
+ regionCode: optionalString(address.regionCode, "address.region_code")?.toUpperCase(),
3110
+ addressLines,
3111
+ locality: optionalString(address.locality, "address.locality"),
3112
+ administrativeArea: optionalString(address.administrativeArea, "address.administrative_area"),
3113
+ postalCode: optionalString(address.postalCode, "address.postal_code")
3114
+ };
3115
+ const length = [
3116
+ ...input.addressLines,
3117
+ input.locality ?? "",
3118
+ input.administrativeArea ?? "",
3119
+ input.postalCode ?? ""
3120
+ ].join("").length;
3121
+ if (length > MAX_INPUT_LENGTH) {
3122
+ throw new ValidationRequestError(
3123
+ `The total length of the address fields must not exceed ${MAX_INPUT_LENGTH} characters.`
3124
+ );
3125
+ }
3126
+ const region = input.regionCode ?? "US";
3127
+ if (enable === true && region !== "US" && region !== "PR") {
3128
+ throw new ValidationRequestError(
3129
+ "USPS CASS validation is only supported for addresses in the US and PR regions."
3130
+ );
3131
+ }
3132
+ return { address: input, enableUspsCass: enable === true };
3133
+ };
3134
+ var ABBREVIATIONS = {
3135
+ north: "N",
3136
+ south: "S",
3137
+ east: "E",
3138
+ west: "W",
3139
+ northeast: "NE",
3140
+ northwest: "NW",
3141
+ southeast: "SE",
3142
+ southwest: "SW",
3143
+ avenue: "Ave",
3144
+ av: "Ave",
3145
+ street: "St",
3146
+ str: "St",
3147
+ road: "Rd",
3148
+ drive: "Dr",
3149
+ boulevard: "Blvd",
3150
+ lane: "Ln",
3151
+ parkway: "Pkwy",
3152
+ place: "Pl",
3153
+ court: "Ct",
3154
+ circle: "Cir",
3155
+ highway: "Hwy",
3156
+ terrace: "Ter",
3157
+ square: "Sq",
3158
+ plaza: "Plz",
3159
+ trail: "Trl",
3160
+ way: "Way",
3161
+ mall: "Mall"
3162
+ };
3163
+ var DIRECTIONALS = /* @__PURE__ */ new Set(["n", "s", "e", "w", "ne", "nw", "se", "sw"]);
3164
+ var DESIGNATORS = {
3165
+ apt: "Apt",
3166
+ apartment: "Apt",
3167
+ unit: "Unit",
3168
+ ste: "Ste",
3169
+ suite: "Ste",
3170
+ bldg: "Bldg",
3171
+ building: "Bldg",
3172
+ fl: "Fl",
3173
+ floor: "Fl",
3174
+ rm: "Rm",
3175
+ room: "Rm",
3176
+ spc: "Spc",
3177
+ space: "Spc",
3178
+ lot: "Lot",
3179
+ trlr: "Trlr",
3180
+ "#": "#"
3181
+ };
3182
+ 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;
3183
+ 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;
3184
+ var STREET_NUMBER2 = /^([A-Za-z]?\d+[A-Za-z]?(?:-\d+)?)\s+(.+)$/;
3185
+ var unitText = (unit) => unit.designator === "#" ? `#${unit.value}` : `${unit.designator} ${unit.value}`;
3186
+ var parseUnit = (designator, value) => ({
3187
+ designator: DESIGNATORS[(designator ?? "#").toLowerCase()] ?? "#",
3188
+ value: value.toUpperCase()
3189
+ });
3190
+ var splitUnit = (line) => {
3191
+ const match = UNIT_AT_END.exec(line);
3192
+ if (!match || match.index === 0) return { street: line.trim(), unit: void 0 };
3193
+ return {
3194
+ street: line.slice(0, match.index).trim(),
3195
+ unit: parseUnit(match[1], match[2])
3196
+ };
3197
+ };
3198
+ var streetKey = (street) => normalize(street).split(" ").map((word) => (ABBREVIATIONS[word] ?? word).toLowerCase()).join(" ");
3199
+ var standardizeStreet = (street) => street.replace(/[.,]/g, " ").split(/\s+/).filter(Boolean).map((word) => {
3200
+ const lower = word.toLowerCase();
3201
+ if (DIRECTIONALS.has(lower)) return lower.toUpperCase();
3202
+ return ABBREVIATIONS[lower] ?? word;
3203
+ }).join(" ");
3204
+ var stateCode = (value) => {
3205
+ if (!value) return void 0;
3206
+ const upper = value.trim().toUpperCase();
3207
+ if (STATE_NAMES[upper]) return upper;
3208
+ const byName = Object.entries(STATE_NAMES).find(([, name]) => name.toUpperCase() === upper);
3209
+ return byName?.[0] ?? upper;
3210
+ };
3211
+ var cityRows = (rows, city, state) => rows.filter(
3212
+ (row2) => normalize(row2.city) === normalize(city) && (state === void 0 || row2.state === state)
3213
+ );
3214
+ var resolve = (input, rows) => {
3215
+ const [first = "", ...rest] = input.addressLines;
3216
+ let streetLine = first;
3217
+ let unit;
3218
+ let locality = input.locality;
3219
+ let state = stateCode(input.administrativeArea);
3220
+ let zip = input.postalCode?.slice(0, 5);
3221
+ let candidates = [];
3222
+ if (locality || zip) {
3223
+ const second = rest.join(" ").trim();
3224
+ if (second) {
3225
+ const only = UNIT_ONLY.exec(second);
3226
+ if (only) unit = parseUnit(only[1], only[2]);
3227
+ }
3228
+ } else {
3229
+ const joined = input.addressLines.join(", ");
3230
+ const parsed = parseStreetInCity(joined, rows);
3231
+ if (parsed) {
3232
+ streetLine = parsed.line1;
3233
+ locality = parsed.row.city;
3234
+ state = parsed.row.state;
3235
+ const zipMatch = /\b(\d{5})(?:-\d{4})?\s*(?:,?\s*(?:USA|US|United States))?$/i.exec(joined);
3236
+ zip = zipMatch?.[1];
3237
+ }
3238
+ }
3239
+ const split = splitUnit(streetLine);
3240
+ const street = split.street;
3241
+ unit = unit ?? split.unit;
3242
+ const numbered = STREET_NUMBER2.exec(street);
3243
+ if (locality) candidates = cityRows(rows, locality, state);
3244
+ let localityStatus = "confirmed";
3245
+ let stateStatus = "confirmed";
3246
+ if (candidates.length === 0 && zip) {
3247
+ candidates = rows.filter((row2) => row2.zip === zip);
3248
+ if (candidates.length > 0) {
3249
+ localityStatus = "replaced";
3250
+ if (state !== void 0 && candidates[0]?.state !== state) stateStatus = "replaced";
3251
+ }
3252
+ }
3253
+ if (candidates.length === 0 || !numbered) {
3254
+ return { unresolved: { street, unit, hasNumber: !!numbered } };
3255
+ }
3256
+ const number = numbered[1];
3257
+ const key = streetKey(street);
3258
+ const exact = candidates.find((row2) => streetKey(row2.line1) === key);
3259
+ const base = exact ?? candidates.find((row2) => zip !== void 0 && row2.zip === zip) ?? candidates[0];
3260
+ const outStreet = exact ? exact.line1 : standardizeStreet(street);
3261
+ const routeMatch = STREET_NUMBER2.exec(outStreet);
3262
+ return {
3263
+ resolved: {
3264
+ row: base,
3265
+ street: outStreet,
3266
+ number,
3267
+ route: routeMatch ? routeMatch[2] : outStreet,
3268
+ unit,
3269
+ inCorpus: !!exact,
3270
+ postal: zip === void 0 ? "inferred" : zip === base.zip ? "confirmed" : "replaced",
3271
+ locality: localityStatus,
3272
+ state: stateStatus
3273
+ }
3274
+ };
3275
+ };
3276
+ var fnv = (value, seed = 2166136261) => {
3277
+ let hash = seed >>> 0;
3278
+ for (let i = 0; i < value.length; i++) {
3279
+ hash ^= value.charCodeAt(i);
3280
+ hash = Math.imul(hash, 16777619) >>> 0;
3281
+ }
3282
+ return hash;
3283
+ };
3284
+ var zipPlus4 = (row2, street) => String(fnv(`${row2.id}|${streetKey(street)}`) % 9999 + 1).padStart(4, "0");
3285
+ var responseId = (seed) => {
3286
+ const hex = [2166136261, 16777619, 2654435769, 2135587861].map((s) => fnv(seed, s).toString(16).padStart(8, "0")).join("");
3287
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-4${hex.slice(13, 16)}-a${hex.slice(17, 20)}-${hex.slice(20, 32)}`;
3288
+ };
3289
+ var component = (text2, componentType, confirmationLevel, flags = {}) => ({
3290
+ componentName: { text: text2, languageCode: "en" },
3291
+ componentType,
3292
+ confirmationLevel,
3293
+ ...flags.inferred ? { inferred: true } : {},
3294
+ ...flags.replaced ? { replaced: true } : {}
3295
+ });
3296
+ var compact = (value) => Object.fromEntries(
3297
+ Object.entries(value).filter(
3298
+ ([, v]) => v !== void 0 && v !== false && !(Array.isArray(v) && v.length === 0)
3299
+ )
3300
+ );
3301
+ var uniq = (values) => [...new Set(values)];
3302
+ var validateAddress = (request, rows, options = {}) => {
3303
+ const { address: input, enableUspsCass } = request;
3304
+ const region = input.regionCode ?? "US";
3305
+ const usps = region === "US" || region === "PR";
3306
+ const outcome = region === "US" ? resolve(input, rows) : void 0;
3307
+ let granularity;
3308
+ let inputGranularity;
3309
+ let addressComplete;
3310
+ let nextAction;
3311
+ let dpv;
3312
+ let dpvFootnote;
3313
+ let unconfirmed = [];
3314
+ let missing = [];
3315
+ let hasReplaced = false;
3316
+ let hasInferred = false;
3317
+ let uspsError;
3318
+ const components = [];
3319
+ let postalAddress;
3320
+ let formattedAddress2;
3321
+ let geocode2;
3322
+ let standardized;
3323
+ let rowId;
3324
+ if (!outcome || "unresolved" in outcome) {
3325
+ const street = outcome && "unresolved" in outcome ? outcome.unresolved : void 0;
3326
+ const hasNumber = street?.hasNumber ?? STREET_NUMBER2.test(input.addressLines[0] ?? "");
3327
+ const unit = street?.unit;
3328
+ const cityKnown = input.locality !== void 0 && cityRows(rows, input.locality, stateCode(input.administrativeArea)).length > 0;
3329
+ inputGranularity = unit ? "SUB_PREMISE" : hasNumber ? "PREMISE" : "ROUTE";
3330
+ addressComplete = false;
3331
+ nextAction = "FIX";
3332
+ if (cityKnown && !hasNumber) {
3333
+ granularity = "ROUTE";
3334
+ missing = ["street_number"];
3335
+ dpv = void 0;
3336
+ } else {
3337
+ granularity = "OTHER";
3338
+ dpv = usps ? "N" : void 0;
3339
+ }
3340
+ const streetText = street?.street ?? input.addressLines[0] ?? "";
3341
+ const split = STREET_NUMBER2.exec(streetText);
3342
+ const routeLevel = cityKnown ? "UNCONFIRMED_BUT_PLAUSIBLE" : "UNCONFIRMED_AND_SUSPICIOUS";
3343
+ if (split) {
3344
+ components.push(component(split[1], "street_number", routeLevel));
3345
+ components.push(component(split[2], "route", routeLevel));
3346
+ } else if (streetText) {
3347
+ components.push(
3348
+ component(streetText, "route", cityKnown ? "CONFIRMED" : "UNCONFIRMED_AND_SUSPICIOUS")
3349
+ );
3350
+ }
3351
+ if (unit) components.push(component(unitText(unit), "subpremise", routeLevel));
3352
+ if (input.locality) {
3353
+ components.push(
3354
+ component(
3355
+ input.locality,
3356
+ "locality",
3357
+ cityKnown ? "CONFIRMED" : "UNCONFIRMED_AND_SUSPICIOUS"
3358
+ )
3359
+ );
3360
+ }
3361
+ const state = stateCode(input.administrativeArea);
3362
+ if (state) {
3363
+ components.push(
3364
+ component(
3365
+ state,
3366
+ "administrative_area_level_1",
3367
+ STATE_NAMES[state] ? "CONFIRMED" : "UNCONFIRMED_AND_SUSPICIOUS"
3368
+ )
3369
+ );
3370
+ }
3371
+ if (input.postalCode) {
3372
+ const zipKnown = rows.some((row2) => row2.zip === input.postalCode?.slice(0, 5));
3373
+ components.push(
3374
+ component(
3375
+ input.postalCode,
3376
+ "postal_code",
3377
+ zipKnown ? "CONFIRMED" : "UNCONFIRMED_AND_SUSPICIOUS"
3378
+ )
3379
+ );
3380
+ }
3381
+ components.push(
3382
+ component(region === "US" ? "USA" : region, "country", "CONFIRMED", {
3383
+ inferred: input.regionCode === void 0
3384
+ })
3385
+ );
3386
+ hasInferred = input.regionCode === void 0;
3387
+ unconfirmed = components.filter((c) => c.confirmationLevel !== "CONFIRMED").map((c) => c.componentType);
3388
+ const line = [streetText, unit ? unitText(unit) : ""].filter(Boolean).join(" ");
3389
+ postalAddress = compact({
3390
+ regionCode: region,
3391
+ languageCode: "en",
3392
+ postalCode: input.postalCode,
3393
+ administrativeArea: state,
3394
+ locality: input.locality,
3395
+ addressLines: line ? [line] : void 0
3396
+ });
3397
+ formattedAddress2 = [
3398
+ line,
3399
+ input.locality,
3400
+ [state, input.postalCode].filter(Boolean).join(" "),
3401
+ region === "US" ? "USA" : region
3402
+ ].filter(Boolean).join(", ");
3403
+ } else {
3404
+ const r = outcome.resolved;
3405
+ const row2 = r.row;
3406
+ rowId = row2.id;
3407
+ const street = r.street;
3408
+ const validation = row2.validation ?? {};
3409
+ const plus4 = zipPlus4(row2, street);
3410
+ inputGranularity = r.unit ? "SUB_PREMISE" : "PREMISE";
3411
+ granularity = "PREMISE";
3412
+ addressComplete = true;
3413
+ nextAction = "ACCEPT";
3414
+ dpv = "Y";
3415
+ dpvFootnote = "AABB";
3416
+ let unitLevel = "CONFIRMED";
3417
+ if (validation.multiUnit) {
3418
+ if (!r.unit) {
3419
+ missing = ["subpremise"];
3420
+ addressComplete = false;
3421
+ nextAction = "CONFIRM_ADD_SUBPREMISES";
3422
+ dpv = "D";
3423
+ dpvFootnote = "AAN1";
3424
+ } else if (validation.units === void 0 || validation.units.some((u) => u.toUpperCase() === r.unit?.value)) {
3425
+ granularity = "SUB_PREMISE";
3426
+ } else {
3427
+ unitLevel = "UNCONFIRMED_BUT_PLAUSIBLE";
3428
+ nextAction = "CONFIRM";
3429
+ dpv = "S";
3430
+ dpvFootnote = "AACC";
3431
+ }
3432
+ } else if (r.unit) {
3433
+ unitLevel = "UNCONFIRMED_BUT_PLAUSIBLE";
3434
+ nextAction = "CONFIRM";
3435
+ dpvFootnote = "AACC";
3436
+ }
3437
+ if (r.postal === "replaced" || r.locality === "replaced" || r.state === "replaced") {
3438
+ hasReplaced = true;
3439
+ if (nextAction === "ACCEPT") nextAction = "CONFIRM";
3440
+ }
3441
+ components.push(component(r.number, "street_number", "CONFIRMED"));
3442
+ components.push(component(r.route, "route", "CONFIRMED"));
3443
+ if (r.unit) components.push(component(unitText(r.unit), "subpremise", unitLevel));
3444
+ components.push(
3445
+ component(row2.city, "locality", "CONFIRMED", { replaced: r.locality === "replaced" })
3446
+ );
3447
+ components.push(
3448
+ component(row2.state, "administrative_area_level_1", "CONFIRMED", {
3449
+ replaced: r.state === "replaced"
3450
+ })
3451
+ );
3452
+ components.push(
3453
+ component(row2.zip, "postal_code", "CONFIRMED", {
3454
+ inferred: r.postal === "inferred",
3455
+ replaced: r.postal === "replaced"
3456
+ })
3457
+ );
3458
+ components.push(component(plus4, "postal_code_suffix", "CONFIRMED", { inferred: true }));
3459
+ components.push(
3460
+ component("USA", "country", "CONFIRMED", { inferred: input.regionCode === void 0 })
3461
+ );
3462
+ hasInferred = true;
3463
+ unconfirmed = components.filter((c) => c.confirmationLevel !== "CONFIRMED").map((c) => c.componentType);
3464
+ if (validation.granularity) granularity = validation.granularity;
3465
+ if (validation.addressComplete !== void 0) addressComplete = validation.addressComplete;
3466
+ if (validation.possibleNextAction) nextAction = validation.possibleNextAction;
3467
+ if (validation.dpvConfirmation) dpv = validation.dpvConfirmation;
3468
+ if (validation.unconfirmedComponentTypes)
3469
+ unconfirmed = [...validation.unconfirmedComponentTypes];
3470
+ if (validation.uspsErrorMessage) uspsError = validation.uspsErrorMessage;
3471
+ const line = [street, r.unit ? unitText(r.unit) : ""].filter(Boolean).join(" ");
3472
+ const zip = `${row2.zip}-${plus4}`;
3473
+ postalAddress = {
3474
+ regionCode: "US",
3475
+ languageCode: "en",
3476
+ postalCode: zip,
3477
+ administrativeArea: row2.state,
3478
+ locality: row2.city,
3479
+ addressLines: [line]
3480
+ };
3481
+ formattedAddress2 = `${line}, ${row2.city}, ${row2.state} ${zip}, USA`;
3482
+ const place = r.inCorpus ? { placeId: corpusPlaceId(row2), lat: row2.lat, lng: row2.lng } : synthesize(street, row2);
3483
+ geocode2 = {
3484
+ location: { latitude: place.lat, longitude: place.lng },
3485
+ placeId: place.placeId,
3486
+ placeTypes: r.unit ? ["subpremise"] : ["premise"]
3487
+ };
3488
+ standardized = {
3489
+ firstAddressLine: line.toUpperCase(),
3490
+ cityStateZipAddressLine: `${row2.city.toUpperCase()} ${row2.state} ${zip}`,
3491
+ city: row2.city.toUpperCase(),
3492
+ state: row2.state,
3493
+ zipCode: row2.zip,
3494
+ zipCodeExtension: plus4
3495
+ };
3496
+ }
3497
+ if (options.dpvOverride) dpv = options.dpvOverride;
3498
+ if (dpv === "N") standardized = void 0;
3499
+ if (dpv !== void 0 && dpvFootnote === void 0) dpvFootnote = dpv === "N" ? "A1M1" : "AABB";
3500
+ if (dpv === "N") dpvFootnote = "A1M1";
3501
+ const verdict = compact({
3502
+ inputGranularity,
3503
+ validationGranularity: granularity,
3504
+ geocodeGranularity: granularity === "SUB_PREMISE" ? "PREMISE" : granularity,
3505
+ addressComplete,
3506
+ hasUnconfirmedComponents: unconfirmed.length > 0,
3507
+ hasInferredComponents: hasInferred,
3508
+ hasReplacedComponents: hasReplaced,
3509
+ possibleNextAction: nextAction
3510
+ });
3511
+ const address = compact({
3512
+ formattedAddress: formattedAddress2,
3513
+ postalAddress,
3514
+ addressComponents: components,
3515
+ missingComponentTypes: uniq(missing),
3516
+ unconfirmedComponentTypes: uniq(unconfirmed)
3517
+ });
3518
+ const uspsData = usps ? uspsError ? compact({ errorMessage: uspsError, cassProcessed: enableUspsCass }) : compact({
3519
+ standardizedAddress: standardized,
3520
+ dpvConfirmation: dpv,
3521
+ dpvFootnote: dpv ? dpvFootnote : void 0,
3522
+ postOfficeCity: standardized ? standardized.city : void 0,
3523
+ postOfficeState: standardized ? standardized.state : void 0,
3524
+ cassProcessed: enableUspsCass
3525
+ }) : void 0;
3526
+ const result = compact({ verdict, address, geocode: geocode2, uspsData });
3527
+ const verdictClass = `${nextAction}/${uspsError ? "ERROR" : dpv ?? "-"}`;
3528
+ return {
3529
+ body: { result, responseId: responseId(JSON.stringify({ input, enableUspsCass })) },
3530
+ rowId,
3531
+ verdictClass
3532
+ };
3533
+ };
3534
+
3013
3535
  // src/runtime.ts
3014
3536
  var WEB_SERVICES = ["PlaceAutocomplete", "PlaceDetails", "Geocode", "FindPlaceFromText"];
3015
3537
  var everyWebService = (rule) => WEB_SERVICES.map((operationId) => ({ operationId, ...rule }));
@@ -3054,6 +3576,60 @@ var GOOGLE_MAPS_PRESETS = {
3054
3576
  description: "Every web-service call is held 6 s: past QA's 5 s wait for predictions",
3055
3577
  rules: everyWebService({ latencyMs: 6e3 })
3056
3578
  },
3579
+ address_validation_denied: {
3580
+ description: "Address Validation answers 403 PERMISSION_DENIED, as for a key without the API enabled",
3581
+ rules: [
3582
+ {
3583
+ operationId: "ValidateAddress",
3584
+ status: 403,
3585
+ body: {
3586
+ error: {
3587
+ code: 403,
3588
+ message: "Requests to this API addressvalidation.googleapis.com method google.maps.addressvalidation.v1.AddressValidation.ValidateAddress are blocked.",
3589
+ status: "PERMISSION_DENIED",
3590
+ details: [
3591
+ {
3592
+ "@type": "type.googleapis.com/google.rpc.ErrorInfo",
3593
+ reason: "API_KEY_SERVICE_BLOCKED",
3594
+ domain: "googleapis.com",
3595
+ metadata: { service: "addressvalidation.googleapis.com" }
3596
+ }
3597
+ ]
3598
+ }
3599
+ }
3600
+ }
3601
+ ]
3602
+ },
3603
+ address_validation_unavailable: {
3604
+ description: "Address Validation answers 503 UNAVAILABLE (Google's transient failure)",
3605
+ rules: [
3606
+ {
3607
+ operationId: "ValidateAddress",
3608
+ status: 503,
3609
+ body: {
3610
+ error: {
3611
+ code: 503,
3612
+ message: "The service is currently unavailable.",
3613
+ status: "UNAVAILABLE"
3614
+ }
3615
+ }
3616
+ }
3617
+ ]
3618
+ },
3619
+ address_validation_slow: {
3620
+ description: "Address Validation is held 3 s: past a 2.5 s checkout timeout",
3621
+ rules: [{ operationId: "ValidateAddress", latencyMs: 3e3 }]
3622
+ },
3623
+ address_validation_no_verdict: {
3624
+ description: `Address Validation answers 200 {"result": {}} (no verdict): a malformed answer, for a client's defensive branch`,
3625
+ rules: [{ operationId: "ValidateAddress", status: 200, body: { result: {} } }]
3626
+ },
3627
+ address_validation_dpv_n: {
3628
+ description: "Address Validation reports USPS DPV confirmation N (not deliverable)",
3629
+ rules: [
3630
+ { operationId: "ValidateAddress", effect: "usps_dpv", params: { dpvConfirmation: "N" } }
3631
+ ]
3632
+ },
3057
3633
  script_unavailable: {
3058
3634
  description: "The Maps JavaScript API answers 503, so the script's onerror fires",
3059
3635
  rules: [{ operationId: "MapsJavaScriptApi", status: 503, body: "Service Unavailable" }]
@@ -3061,9 +3637,46 @@ var GOOGLE_MAPS_PRESETS = {
3061
3637
  };
3062
3638
  var json3 = (status, body) => new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json" } });
3063
3639
  var adminError3 = (status, message) => json3(status, { error: { type: "mockingbird_admin", message } });
3064
- var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
3640
+ var isRecord5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
3641
+ var stringList = (value) => Array.isArray(value) && value.every((v) => typeof v === "string") ? value : void 0;
3642
+ var parseValidation = (value, index) => {
3643
+ if (value === void 0 || value === null) return void 0;
3644
+ const at = `addresses[${index}].validation`;
3645
+ if (!isRecord5(value)) return `${at} must be an object`;
3646
+ const out = {};
3647
+ const enums = [
3648
+ ["granularity", GRANULARITIES],
3649
+ ["possibleNextAction", NEXT_ACTIONS],
3650
+ ["dpvConfirmation", DPV_CODES]
3651
+ ];
3652
+ for (const [key, allowed] of enums) {
3653
+ if (value[key] === void 0) continue;
3654
+ if (!allowed.includes(value[key])) {
3655
+ return `${at}.${key} must be one of ${allowed.join(", ")}`;
3656
+ }
3657
+ Object.assign(out, { [key]: value[key] });
3658
+ }
3659
+ for (const key of ["addressComplete", "multiUnit"]) {
3660
+ if (value[key] === void 0) continue;
3661
+ if (typeof value[key] !== "boolean") return `${at}.${key} must be a boolean`;
3662
+ out[key] = value[key];
3663
+ }
3664
+ for (const key of ["unconfirmedComponentTypes", "units"]) {
3665
+ if (value[key] === void 0) continue;
3666
+ const list = stringList(value[key]);
3667
+ if (!list) return `${at}.${key} must be a string[]`;
3668
+ out[key] = list;
3669
+ }
3670
+ if (value.uspsErrorMessage !== void 0) {
3671
+ if (typeof value.uspsErrorMessage !== "string" || !value.uspsErrorMessage) {
3672
+ return `${at}.uspsErrorMessage must be a non-empty string`;
3673
+ }
3674
+ out.uspsErrorMessage = value.uspsErrorMessage;
3675
+ }
3676
+ return out;
3677
+ };
3065
3678
  var parseAddress = (value, index) => {
3066
- if (!isRecord4(value)) return `addresses[${index}] must be an object`;
3679
+ if (!isRecord5(value)) return `addresses[${index}] must be an object`;
3067
3680
  for (const key of ["line1", "city", "state", "zip"]) {
3068
3681
  if (typeof value[key] !== "string" || !value[key].trim()) {
3069
3682
  return `addresses[${index}].${key} must be a non-empty string`;
@@ -3071,6 +3684,8 @@ var parseAddress = (value, index) => {
3071
3684
  }
3072
3685
  const state = String(value.state).toUpperCase();
3073
3686
  if (!/^[A-Z]{2}$/.test(state)) return `addresses[${index}].state must be a two-letter code`;
3687
+ const validation = parseValidation(value.validation, index);
3688
+ if (typeof validation === "string") return validation;
3074
3689
  const lat = value.lat === void 0 ? 0 : Number(value.lat);
3075
3690
  const lng = value.lng === void 0 ? 0 : Number(value.lng);
3076
3691
  if (!Number.isFinite(lat) || !Number.isFinite(lng)) {
@@ -3084,7 +3699,8 @@ var parseAddress = (value, index) => {
3084
3699
  zip: String(value.zip).trim(),
3085
3700
  county: typeof value.county === "string" ? value.county : "",
3086
3701
  lat,
3087
- lng
3702
+ lng,
3703
+ ...validation ? { validation } : {}
3088
3704
  };
3089
3705
  };
3090
3706
  var adminRoutes = (runtime) => ({
@@ -3096,9 +3712,12 @@ var adminRoutes = (runtime) => ({
3096
3712
  });
3097
3713
  },
3098
3714
  "PUT /corpus": ({ body, namespace }) => {
3099
- const list = Array.isArray(body) ? body : isRecord4(body) ? body.addresses : void 0;
3715
+ const list = Array.isArray(body) ? body : isRecord5(body) ? body.addresses : void 0;
3100
3716
  if (!Array.isArray(list)) {
3101
- return adminError3(400, 'expected {"addresses": [{line1, city, state, zip, lat?, lng?}]}');
3717
+ return adminError3(
3718
+ 400,
3719
+ 'expected {"addresses": [{line1, city, state, zip, lat?, lng?, validation?}]}'
3720
+ );
3102
3721
  }
3103
3722
  const rows = [];
3104
3723
  for (const [index, each] of list.entries()) {
@@ -3116,7 +3735,7 @@ var adminRoutes = (runtime) => ({
3116
3735
  },
3117
3736
  "GET /settings": ({ namespace }) => json3(200, runtime.instance(namespace).state.current()),
3118
3737
  "PUT /settings": ({ body, namespace }) => {
3119
- if (!isRecord4(body)) return adminError3(400, "expected a JSON object");
3738
+ if (!isRecord5(body)) return adminError3(400, "expected a JSON object");
3120
3739
  const patch = {};
3121
3740
  if (body.keys !== void 0) {
3122
3741
  if (!Array.isArray(body.keys)) return adminError3(400, "keys: string[]");
@@ -3159,7 +3778,9 @@ var createRuntime2 = (options = {}) => createRuntime({
3159
3778
  var GOOGLE_MAPS_NAMESPACE = "google-maps";
3160
3779
  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
3780
  var INVALID_KEY_MESSAGE = "The provided API key is invalid. ";
3162
- var keyCredential = (request) => new URL(request.url).searchParams.get("key") ?? void 0;
3781
+ var MISSING_API_KEY_MESSAGE = "The request is missing a valid API key.";
3782
+ var INVALID_API_KEY_MESSAGE = "API key not valid. Please pass a valid API key.";
3783
+ var keyCredential = (request) => new URL(request.url).searchParams.get("key") ?? request.headers.get("x-goog-api-key") ?? void 0;
3163
3784
  var CORS = { "access-control-allow-origin": "*" };
3164
3785
  var json4 = (body, status = 200) => new Response(JSON.stringify(body, null, 3), {
3165
3786
  status,
@@ -3176,6 +3797,17 @@ var DEFAULT_MESSAGES = {
3176
3797
  UNKNOWN_ERROR: "An unknown error occurred. Please try again.",
3177
3798
  REQUEST_DENIED: INVALID_KEY_MESSAGE
3178
3799
  };
3800
+ var apiError = (error) => json4({ error }, error.code);
3801
+ var requestJson = (body) => {
3802
+ if (body.kind === "json") return body.value;
3803
+ if (body.kind === "empty") return {};
3804
+ const raw = body.kind === "bytes" ? new TextDecoder().decode(body.value) : body.kind === "text" ? body.value : body.kind === "invalid" ? body.text : void 0;
3805
+ try {
3806
+ return JSON.parse(raw ?? "");
3807
+ } catch {
3808
+ throw new ValidationRequestError("Invalid JSON payload received.");
3809
+ }
3810
+ };
3179
3811
  var text = (value) => typeof value === "string" ? value : Array.isArray(value) ? String(value[0]) : void 0;
3180
3812
  var GoogleMapsAPI = class {
3181
3813
  app;
@@ -3196,7 +3828,8 @@ var GoogleMapsAPI = class {
3196
3828
  PlaceDetails: (context) => this.details(context),
3197
3829
  Geocode: (context) => this.geocode(context),
3198
3830
  FindPlaceFromText: (context) => this.findPlace(context),
3199
- MapsJavaScriptApi: (context) => this.script(context)
3831
+ MapsJavaScriptApi: (context) => this.script(context),
3832
+ ValidateAddress: (context) => this.validate(context)
3200
3833
  });
3201
3834
  this.service = createService({
3202
3835
  document,
@@ -3239,6 +3872,7 @@ var GoogleMapsAPI = class {
3239
3872
  gate(context) {
3240
3873
  const operationId = context.operation.operationId;
3241
3874
  if (operationId === "MapsJavaScriptApi") return void 0;
3875
+ if (operationId === "ValidateAddress") return this.cloudGate(context);
3242
3876
  const key = text(context.query.key);
3243
3877
  if (!key) return this.status(operationId, "REQUEST_DENIED", MISSING_KEY_MESSAGE);
3244
3878
  const keys = this.state.current().keys;
@@ -3253,6 +3887,50 @@ var GoogleMapsAPI = class {
3253
3887
  }
3254
3888
  return void 0;
3255
3889
  }
3890
+ /** Key check for the Google Cloud-style Address Validation API. */
3891
+ cloudGate(context) {
3892
+ const key = text(context.query.key) ?? context.request.headers.get("x-goog-api-key");
3893
+ if (!key) {
3894
+ return apiError({ code: 403, message: MISSING_API_KEY_MESSAGE, status: "PERMISSION_DENIED" });
3895
+ }
3896
+ const keys = this.state.current().keys;
3897
+ if (keys.length > 0 && !keys.includes(key)) {
3898
+ return apiError({
3899
+ code: 400,
3900
+ message: INVALID_API_KEY_MESSAGE,
3901
+ status: "INVALID_ARGUMENT",
3902
+ details: [
3903
+ {
3904
+ "@type": "type.googleapis.com/google.rpc.ErrorInfo",
3905
+ reason: "API_KEY_INVALID",
3906
+ domain: "googleapis.com",
3907
+ metadata: { service: "addressvalidation.googleapis.com" }
3908
+ }
3909
+ ]
3910
+ });
3911
+ }
3912
+ return void 0;
3913
+ }
3914
+ validate(context) {
3915
+ let request;
3916
+ try {
3917
+ request = parseValidateRequest(requestJson(context.body));
3918
+ } catch (error) {
3919
+ if (!(error instanceof ValidationRequestError)) throw error;
3920
+ return apiError({ code: 400, message: error.message, status: "INVALID_ARGUMENT" });
3921
+ }
3922
+ const forced = faultEffect(context.request, "usps_dpv")?.dpvConfirmation;
3923
+ const dpvOverride = DPV_CODES.includes(forced) ? forced : void 0;
3924
+ const outcome = validateAddress(request, this.state.corpus(), {
3925
+ ...dpvOverride ? { dpvOverride } : {}
3926
+ });
3927
+ return annotateResponse(json4(outcome.body), {
3928
+ ids: {
3929
+ ...outcome.rowId ? { addressRowId: outcome.rowId } : {},
3930
+ verdict: outcome.verdictClass
3931
+ }
3932
+ });
3933
+ }
3256
3934
  noted(response, context, place) {
3257
3935
  const session = text(context.query.sessiontoken);
3258
3936
  const ids = {};
@@ -3387,7 +4065,9 @@ export {
3387
4065
  GOOGLE_MAPS_NAMESPACE,
3388
4066
  MISSING_KEY_MESSAGE,
3389
4067
  INVALID_KEY_MESSAGE,
4068
+ MISSING_API_KEY_MESSAGE,
4069
+ INVALID_API_KEY_MESSAGE,
3390
4070
  keyCredential,
3391
4071
  GoogleMapsAPI
3392
4072
  };
3393
- //# sourceMappingURL=chunk-5HEE5U7V.js.map
4073
+ //# sourceMappingURL=chunk-5OK5LOSY.js.map