Skip to content

Commit 62e96ee

Browse files
authored
Merge pull request #116 from smarty/cami/features-component-analysis
Cami/features component analysis
2 parents 1bb04c5 + 5b49c5d commit 62e96ee

File tree

7 files changed

+234
-88
lines changed

7 files changed

+234
-88
lines changed

examples/us_street.mjs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,29 @@ const credentials = new SmartyCore.SharedCredentials(key);
1515
// The appropriate license values to be used for your subscriptions
1616
// can be found on the Subscription page of the account dashboard.
1717
// https://www.smarty.com/docs/cloud/licensing
18-
let clientBuilder = new SmartyCore.ClientBuilder(credentials).withLicenses(["us-rooftop-geocoding-cloud"]);
19-
// .withBaseUrl("YOUR URL") // withBaseUrl() should be used if you are self-hosting the Smarty API
18+
let clientBuilder = new SmartyCore.ClientBuilder(credentials).withLicenses([
19+
"us-rooftop-geocoding-cloud",
20+
]);
21+
// .withBaseUrl("YOUR URL") // withBaseUrl() should be used if you are self-hosting the Smarty API
2022

2123
let client = clientBuilder.buildUsStreetApiClient();
2224

2325
// Documentation for input fields can be found at:
2426
// https://www.smarty.com/docs/us-street-api#input-fields
2527

2628
let lookup1 = new Lookup();
27-
lookup1.inputId = "24601"; // Optional ID from your system
29+
lookup1.inputId = "24601"; // Optional ID from your system
2830
lookup1.addressee = "John Doe";
2931
lookup1.street = "330 N 100 W";
3032
lookup1.street2 = "closet under the stairs";
3133
lookup1.secondary = "APT 2";
32-
lookup1.urbanization = ""; // Only applies to Puerto Rico addresses
34+
lookup1.urbanization = ""; // Only applies to Puerto Rico addresses
3335
lookup1.city = "Provo";
3436
lookup1.state = "Utah";
3537
lookup1.zipCode = "84601";
3638
lookup1.maxCandidates = 3;
37-
lookup1.match = "invalid"; // "invalid" is the most permissive match,
38-
// this will always return at least one result even if the address is invalid.
39-
// Refer to the documentation for additional MatchStrategy options.
39+
lookup1.match = "enhanced"; // The API will return detailed output based on a more aggressive matching mechanism. It also includes a more comprehensive address dataset beyond just the postal address data. Requires a US Core license or a US Rooftop Geocoding license.
40+
// Refer to the documentation for additional MatchStrategy options.
4041

4142
let lookup2 = new Lookup();
4243
lookup2.street = "1600 Amphitheater Pkwy";
@@ -59,7 +60,7 @@ batch.add(lookup3);
5960
await handleResponse(batch);
6061

6162
function handleSuccess(response) {
62-
response.lookups.map(lookup => console.log(lookup.result));
63+
response.lookups.map((lookup) => console.log(lookup.result));
6364
}
6465

6566
function handleError(response) {
@@ -70,7 +71,7 @@ async function handleResponse(lookup) {
7071
try {
7172
const result = await client.send(lookup);
7273
handleSuccess(result);
73-
} catch(err) {
74+
} catch (err) {
7475
handleError(err);
7576
}
76-
}
77+
}

package-lock.json

Lines changed: 8 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/ClientBuilder.js

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const SharedCredentials = require("./SharedCredentials");
77
const CustomHeaderSender = require("./CustomHeaderSender");
88
const StatusCodeSender = require("./StatusCodeSender");
99
const LicenseSender = require("./LicenseSender");
10+
const CustomQuerySender = require("@/src/CustomQuerySender");
1011
const BadCredentialsError = require("./Errors").BadCredentialsError;
1112
const RetrySender = require("./RetrySender");
1213
const Sleeper = require("./util/Sleeper.ts");
@@ -39,7 +40,7 @@ const INTERNATIONAL_POSTAL_CODE_API_URL = "https://international-postal-code.api
3940
*/
4041
class ClientBuilder {
4142
constructor(signer) {
42-
if (noCredentialsProvided()) throw new BadCredentialsError();
43+
if (!credentialsProvided()) throw new BadCredentialsError();
4344

4445
this.signer = signer;
4546
this.httpSender = undefined;
@@ -50,15 +51,16 @@ class ClientBuilder {
5051
this.customHeaders = {};
5152
this.debug = undefined;
5253
this.licenses = [];
54+
this.customQueries = new Map();
5355

54-
function noCredentialsProvided() {
55-
return (!signer) instanceof StaticCredentials || (!signer) instanceof SharedCredentials;
56+
function credentialsProvided() {
57+
return signer instanceof StaticCredentials || signer instanceof SharedCredentials;
5658
}
5759
}
5860

5961
/**
6062
* @param retries The maximum number of times to retry sending the request to the API. (Default is 5)
61-
* @return Returns <b>this</b> to accommodate method chaining.
63+
* @return ClientBuilder <b>this</b> to accommodate method chaining.
6264
*/
6365
withMaxRetries(retries) {
6466
this.maxRetries = retries;
@@ -68,7 +70,7 @@ class ClientBuilder {
6870
/**
6971
* @param timeout The maximum time (in milliseconds) to wait for a connection, and also to wait for <br>
7072
* the response to be read. (Default is 10000)
71-
* @return Returns <b>this</b> to accommodate method chaining.
73+
* @return ClientBuilder <b>this</b> to accommodate method chaining.
7274
*/
7375
withMaxTimeout(timeout) {
7476
this.maxTimeout = timeout;
@@ -77,7 +79,7 @@ class ClientBuilder {
7779

7880
/**
7981
* @param sender Default is a series of nested senders. See <b>buildSender()</b>.
80-
* @return Returns <b>this</b> to accommodate method chaining.
82+
* @return ClientBuilder <b>this</b> to accommodate method chaining.
8183
*/
8284
withSender(sender) {
8385
this.httpSender = sender;
@@ -87,7 +89,7 @@ class ClientBuilder {
8789
/**
8890
* This may be useful when using a local installation of the Smarty APIs.
8991
* @param url Defaults to the URL for the API corresponding to the <b>Client</b> object being built.
90-
* @return Returns <b>this</b> to accommodate method chaining.
92+
* @return ClientBuilder <b>this</b> to accommodate method chaining.
9193
*/
9294
withBaseUrl(url) {
9395
this.baseUrl = url;
@@ -101,7 +103,7 @@ class ClientBuilder {
101103
* @param protocol The protocol on the proxy server to which you wish to connect. If the proxy server uses HTTPS, then you must set the protocol to 'https'.
102104
* @param username The username to login to the proxy.
103105
* @param password The password to login to the proxy.
104-
* @return Returns <b>this</b> to accommodate method chaining.
106+
* @return ClientBuilder <b>this</b> to accommodate method chaining.
105107
*/
106108
withProxy(host, port, protocol, username, password) {
107109
this.proxy = {
@@ -123,35 +125,68 @@ class ClientBuilder {
123125
/**
124126
* Use this to add any additional headers you need.
125127
* @param customHeaders A String to Object <b>Map</b> of header name/value pairs.
126-
* @return Returns <b>this</b> to accommodate method chaining.
128+
* @return ClientBuilder <b>this</b> to accommodate method chaining.
127129
*/
128130
withCustomHeaders(customHeaders) {
129131
this.customHeaders = customHeaders;
130-
131132
return this;
132133
}
133134

134135
/**
135136
* Enables debug mode, which will print information about the HTTP request and response to console.log
136-
* @return Returns <b>this</b> to accommodate method chaining.
137+
* @return ClientBuilder <b>this</b> to accommodate method chaining.
137138
*/
138139
withDebug() {
139140
this.debug = true;
140-
141141
return this;
142142
}
143143

144144
/**
145145
* Allows the caller to specify the subscription license (aka "track") they wish to use.
146146
* @param licenses A String Array of licenses.
147-
* @returns Returns <b>this</b> to accommodate method chaining.
147+
* @returns ClientBuilder <b>this</b> to accommodate method chaining.
148148
*/
149149
withLicenses(licenses) {
150150
this.licenses = licenses;
151+
return this;
152+
}
153+
154+
/**
155+
* Allows the caller to specify key and value pair that is added to the request
156+
* @param {string} key - The query parameter key
157+
* @param {string} value - The query parameter value
158+
* @return ClientBuilder <b>this</b> to accommodate method chaining.
159+
*/
160+
withCustomQuery(key, value) {
161+
this.customQueries.set(key, value);
162+
return this;
163+
}
151164

165+
/**
166+
* Allows the caller to specify key and value pair and appends the value associated with the key, seperated by a comma.
167+
* @param {string} key - The query parameter key
168+
* @param {string} value - The query parameter value
169+
* @return ClientBuilder <b>this</b> to accommodate method chaining.
170+
*/
171+
withCustomCommaSeperatedQuery(key, value) {
172+
let values = this.customQueries.get(key);
173+
if (values === "") {
174+
values = value;
175+
} else {
176+
values += "," + value;
177+
}
178+
this.customQueries.set(key, values);
152179
return this;
153180
}
154181

182+
/**
183+
* Adds to the request query to use the component analysis feature.
184+
* @return ClientBuilder <b>this</b> to accommodate method chaining.
185+
*/
186+
withFeatureComponentAnalysis() {
187+
return this.withCustomCommaSeperatedQuery("features", "component-analysis");
188+
}
189+
155190
buildSender() {
156191
if (this.httpSender) return this.httpSender;
157192

@@ -166,8 +201,9 @@ class ClientBuilder {
166201
const customHeaderSender = new CustomHeaderSender(agentSender, this.customHeaders);
167202
const baseUrlSender = new BaseUrlSender(customHeaderSender, this.baseUrl);
168203
const licenseSender = new LicenseSender(baseUrlSender, this.licenses);
204+
const customQuerySender = new CustomQuerySender(licenseSender, this.customQueries);
169205

170-
return licenseSender;
206+
return customQuerySender;
171207
}
172208

173209
buildClient(baseUrl, Client) {

src/CustomQuerySender.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Request, Response, Sender } from "./types";
2+
3+
export default class CustomQuerySender {
4+
private queries: Map<string, string>;
5+
private sender: Sender;
6+
7+
constructor(innerSender: Sender, queries: Map<string, string>) {
8+
this.queries = queries;
9+
this.sender = innerSender;
10+
}
11+
12+
send(request: Request): Promise<Response> {
13+
this.queries.forEach((value, key) => {
14+
const existingValue = request.parameters[key];
15+
request.parameters[key] = existingValue ? `${existingValue},${value}` : value;
16+
});
17+
18+
return this.sender.send(request);
19+
}
20+
}

src/us_street/Candidate.js

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ class Candidate {
5353
this.metadata.elotSort = responseData.metadata.elot_sort;
5454
this.metadata.latitude = responseData.metadata.latitude;
5555
this.metadata.longitude = responseData.metadata.longitude;
56-
switch (responseData.metadata.coordinate_license)
57-
{
56+
switch (responseData.metadata.coordinate_license) {
5857
case 1:
5958
this.metadata.coordinateLicense = "SmartyStreets Proprietary";
6059
break;
@@ -82,8 +81,33 @@ class Candidate {
8281
this.analysis.lacsLinkIndicator = responseData.analysis.lacslink_indicator;
8382
this.analysis.isSuiteLinkMatch = responseData.analysis.suitelink_match;
8483
this.analysis.enhancedMatch = responseData.analysis.enhanced_match;
84+
this.analysis.components = {};
85+
console.log("what are the analysis", responseData.analysis);
86+
if (responseData.analysis.components !== undefined) {
87+
this.analysis.components.primaryNumber = responseData.analysis.components.primary_number;
88+
this.analysis.components.streetPredirection =
89+
responseData.analysis.components.street_predirection;
90+
this.analysis.components.streetName = responseData.analysis.components.street_name;
91+
this.analysis.components.streetPostdirection =
92+
responseData.analysis.components.street_postdirection;
93+
this.analysis.components.streetSuffix = responseData.analysis.components.street_suffix;
94+
this.analysis.components.secondaryNumber =
95+
responseData.analysis.components.secondary_number;
96+
this.analysis.components.secondaryDesignator =
97+
responseData.analysis.components.secondary_designator;
98+
this.analysis.components.extraSecondaryNumber =
99+
responseData.analysis.components.extra_secondary_number;
100+
this.analysis.components.extraSecondaryDesignator =
101+
responseData.analysis.components.extra_secondary_designator;
102+
this.analysis.components.cityName = responseData.analysis.components.city_name;
103+
this.analysis.components.stateAbbreviation =
104+
responseData.analysis.components.state_abbreviation;
105+
this.analysis.components.zipCode = responseData.analysis.components.zipcode;
106+
this.analysis.components.plus4Code = responseData.analysis.components.plus4_code;
107+
this.analysis.components.urbanization = responseData.analysis.components.urbanization;
108+
}
85109
}
86110
}
87111
}
88112

89-
module.exports = Candidate;
113+
module.exports = Candidate;

0 commit comments

Comments
 (0)