diff --git a/.claude/settings.json b/.claude/settings.json index 1210e2a..7b1927f 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -1,16 +1,9 @@ { - "permissions": { - "allow": [ - "Edit", - "Write", - "Bash(rm:./*)", - "Bash(git *)", - "Bash(make *)", - "Bash(npm *)" - ] - }, - "attribution": { - "commit": "", - "pr": "" - } + "permissions": { + "allow": ["Edit", "Write", "Bash(rm:./*)", "Bash(git *)", "Bash(make *)", "Bash(npm *)"] + }, + "attribution": { + "commit": "", + "pr": "" + } } diff --git a/.github/workflows/node-tests.yml b/.github/workflows/node-tests.yml index fdafee4..ee0d9dc 100644 --- a/.github/workflows/node-tests.yml +++ b/.github/workflows/node-tests.yml @@ -2,13 +2,12 @@ name: Node Tests on: push: - branches: [ master ] + branches: [master] pull_request: - branches: [ master ] + branches: [master] jobs: build: - runs-on: ubuntu-latest strategy: @@ -16,13 +15,13 @@ jobs: node-version: [20.x, 22.x, 24.x] steps: - - uses: actions/checkout@v6 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v6 - with: - node-version: ${{ matrix.node-version }} - - run: npm ci - - run: npm run build - - run: npm test - env: - CI: true + - uses: actions/checkout@v6 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v6 + with: + node-version: ${{ matrix.node-version }} + - run: npm ci + - run: npm run build + - run: npm test + env: + CI: true diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4b69d01..986b7ac 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -3,10 +3,10 @@ name: Publish to npm on: push: tags: - - '*' + - "*" permissions: - id-token: write # Required for OIDC + id-token: write # Required for OIDC contents: read jobs: @@ -19,8 +19,8 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v6 with: - node-version: '20.x' - registry-url: 'https://registry.npmjs.org' + node-version: "20.x" + registry-url: "https://registry.npmjs.org" - name: Update npm run: npm install -g npm@'>=11.5.1' @@ -44,4 +44,4 @@ jobs: run: npm publish env: NPM_CONFIG_PROVENANCE: true - NPM_TOKEN: '' + NPM_TOKEN: "" diff --git a/CHANGELOG.md b/CHANGELOG.md index f6c8e34..3527620 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,4 +2,4 @@ See the changelog repository: -github.com/smartystreets/changelog/blob/master/sdk/javascript.md \ No newline at end of file +github.com/smartystreets/changelog/blob/master/sdk/javascript.md diff --git a/CLAUDE.md b/CLAUDE.md index bc88c23..5eee38c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,25 +6,23 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ```bash npm install # Install dependencies -npm test # Run all tests (JS + TS) -npm run test:js # Run JavaScript tests only -npm run test:ts # Run TypeScript tests only +npm test # Run all tests npm run build # Build the library (outputs to dist/) npx tsc --noEmit # Type-check without emitting npx prettier --write src/ # Format source files ``` To run a single test file: + ```bash -npx mocha tests/us_street/test_Client.js # JS test -npx mocha --require tsx/cjs tests/test_RetrySender.ts # TS test +npx mocha --require tsx/cjs tests/test_RetrySender.ts ``` Build outputs dual formats via Rollup: `dist/cjs/` (CommonJS), `dist/esm/` (ESM), and `dist/types/` (declarations). Axios and axios-retry are external dependencies (not bundled). ## Architecture -This is the official JavaScript SDK for Smarty address validation APIs. It supports both Node.js (CommonJS/ESM) and browser environments. +This is the official JavaScript SDK for Smarty address validation APIs. It supports both Node.js (CommonJS/ESM) and browser environments. The entire codebase is TypeScript. ### Sender Chain Pattern @@ -41,37 +39,40 @@ Each sender adds specific functionality (authentication, retries, headers, etc.) - **ClientBuilder**: Fluent API for configuring and building API-specific clients. Accepts either `StaticCredentials` (server-side: auth-id + auth-token) or `SharedCredentials` (client-side: embedded key). -- **Lookup classes**: Each API has a `Lookup` that holds both input parameters and results after the API call. Located in `src//Lookup.js`. +- **Lookup classes**: Each API has a `Lookup` that holds both input parameters and results after the API call. Located in `src//Lookup.ts`. - **Batch**: Container for up to 100 lookups. Single lookups use GET requests; batches with 2+ lookups use POST. -- **Client classes**: Each API has a `Client` in `src//Client.js` that handles domain-specific request building and response parsing. +- **Client classes**: Each API has a `Client` in `src//Client.ts` that handles domain-specific request building and response parsing. ### API Modules Each API follows the same structure in `src//`: -- `Lookup.js` - Input/output container -- `Client.js` - Request/response handling -- `Candidate.js`, `Result.js`, or `Suggestion.js` - Response data structures + +- `Lookup.ts` - Input/output container +- `Client.ts` - Request/response handling +- `Candidate.ts`, `Result.ts`, or `Suggestion.ts` - Response data structures Supported APIs: `us_street`, `us_zipcode`, `us_autocomplete_pro`, `us_extract`, `us_enrichment`, `us_reverse_geo`, `international_street`, `international_address_autocomplete`, `international_postal_code` ### Credentials Three credential types, each implementing a `sign(request)` method used by `SigningSender`: -- **StaticCredentials** (TS) - Server-side: adds `auth-id` + `auth-token` query params -- **SharedCredentials** (TS) - Client-side/browser: adds embedded `key` param + `Referer` header. Cannot be used with POST (batch) requests. -- **BasicAuthCredentials** (TS) - Adds HTTP Basic Auth `Authorization` header + +- **StaticCredentials** - Server-side: adds `auth-id` + `auth-token` query params +- **SharedCredentials** - Client-side/browser: adds embedded `key` param + `Referer` header. Cannot be used with POST (batch) requests. +- **BasicAuthCredentials** - Adds HTTP Basic Auth `Authorization` header ### Entry Point -`index.mjs` exports all public classes organized by API namespace (e.g., `core`, `usStreet`, `usZipcode`). +`index.ts` exports all public classes organized by API namespace (e.g., `core`, `usStreet`, `usZipcode`). ### Test Infrastructure Tests use Mocha + Chai (`expect` style). Test files are prefixed with `test_` and mirror the source structure under `tests/`. -`tests/fixtures/mock_senders.js` provides reusable mocks: +`tests/fixtures/mock_senders.ts` provides reusable mocks: + - `MockSender` - Captures the request for inspection - `MockSenderWithResponse` - Returns a fixed payload/error - `MockSenderWithStatusCodesAndHeaders` - Iterates through status codes (useful for retry tests) @@ -79,6 +80,7 @@ Tests use Mocha + Chai (`expect` style). Test files are prefixed with `test_` an ## Code Style - Uses Prettier: tabs, double quotes, 100 char line width, trailing commas -- Mixed JS/TS: Business logic (clients, lookups, results) in JS; infrastructure (credentials, senders, types) in TS +- All source and test files are TypeScript with ES module syntax (`import`/`export`) +- Import paths use `.js` extensions (TypeScript resolves `.js` to `.ts`) - Tests use Mocha + Chai with `expect` style assertions - Test files are prefixed with `test_` and mirror the source structure diff --git a/LICENSE.md b/LICENSE.md index e1b2a06..dd38c28 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,182 +1,181 @@ - Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" @@ -187,16 +186,16 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2022 Smarty +Copyright 2022 Smarty - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..25a5f5f --- /dev/null +++ b/README.md @@ -0,0 +1,145 @@ +#### SMARTY DISCLAIMER: Subject to the terms of the associated license agreement, this software is freely available for your use. This software is FREE, AS IN PUPPIES, and is a gift. Enjoy your new responsibility. This means that while we may consider enhancement requests, we may or may not choose to entertain requests at our sole and absolute discretion. + + +# Smarty JavaScript SDK + +The official JavaScript/TypeScript SDK for accessing [Smarty](https://www.smarty.com) address validation APIs. Works in both Node.js and browser environments. + +[![npm](https://img.shields.io/npm/v/smartystreets-javascript-sdk)](https://www.npmjs.com/package/smartystreets-javascript-sdk) +[![license](https://img.shields.io/npm/l/smartystreets-javascript-sdk)](LICENSE.md) + +## Installation + +```bash +npm install smartystreets-javascript-sdk +``` + +## Quick Start: US Street Address Validation + +```javascript +import SmartySDK from "smartystreets-javascript-sdk"; + +const credentials = new SmartySDK.core.StaticCredentials( + process.env.SMARTY_AUTH_ID, + process.env.SMARTY_AUTH_TOKEN, +); +const client = new SmartySDK.core.ClientBuilder(credentials).buildUsStreetApiClient(); + +const lookup = new SmartySDK.usStreet.Lookup(); +lookup.street = "1600 Amphitheatre Parkway"; +lookup.city = "Mountain View"; +lookup.state = "CA"; + +const response = await client.send(lookup); +console.log(response.lookups[0].result); +``` + +## Quick Start: US Autocomplete Pro + +```javascript +const client = new SmartySDK.core.ClientBuilder(credentials).buildUsAutocompleteProClient(); + +const lookup = new SmartySDK.usAutocompletePro.Lookup("4770 Lincoln"); +lookup.maxResults = 10; +lookup.preferStates = ["IL"]; + +const response = await client.send(lookup); +console.log(response.result); // Array of address suggestions +``` + +## Supported APIs + +| API | Module | Build Method | Example | +| --- | --- | --- | --- | +| [US Street](https://www.smarty.com/docs/cloud/us-street-api) | `usStreet` | `buildUsStreetApiClient()` | [example](examples/us_street.mjs) | +| [US Zipcode](https://www.smarty.com/docs/cloud/us-zipcode-api) | `usZipcode` | `buildUsZipcodeClient()` | [example](examples/us_zipcode.mjs) | +| [US Autocomplete Pro](https://www.smarty.com/docs/cloud/us-autocomplete-pro-api) | `usAutocompletePro` | `buildUsAutocompleteProClient()` | [example](examples/us_autocomplete_pro.mjs) | +| [US Extract](https://www.smarty.com/docs/cloud/us-extract-api) | `usExtract` | `buildUsExtractClient()` | [example](examples/us_extract.mjs) | +| [US Enrichment](https://www.smarty.com/docs/cloud/us-address-enrichment-api) | `usEnrichment` | `buildUsEnrichmentClient()` | [example](examples/us_enrichment.mjs) | +| [US Reverse Geocoding](https://www.smarty.com/docs/cloud/us-reverse-geo-api) | `usReverseGeo` | `buildUsReverseGeoClient()` | [example](examples/us_reverse_geo.mjs) | +| [International Street](https://www.smarty.com/docs/cloud/international-street-api) | `internationalStreet` | `buildInternationalStreetClient()` | [example](examples/international_street.mjs) | +| [International Autocomplete](https://www.smarty.com/docs/cloud/international-address-autocomplete-api) | `internationalAddressAutocomplete` | `buildInternationalAddressAutocompleteClient()` | [example](examples/international_address_autocomplete.mjs) | +| [International Postal Code](https://www.smarty.com/docs/cloud/international-postal-code-api) | `internationalPostalCode` | `buildInternationalPostalCodeClient()` | [example](examples/international_postal_code.mjs) | + +## Authentication + +Three credential types are available: + +- **`StaticCredentials(authId, authToken)`** — Server-side authentication using auth-id and auth-token. +- **`SharedCredentials(key)`** — Client-side (browser) authentication using an embedded key. Does not support batch (POST) requests. +- **`BasicAuthCredentials(authId, authToken)`** — HTTP Basic Auth. + +## Common Patterns + +### Batch Requests + +Send up to 100 lookups in a single request (not available with `SharedCredentials`): + +```javascript +const batch = new SmartySDK.core.Batch(); +batch.add(lookup1); +batch.add(lookup2); + +const response = await client.send(batch); +``` + +### Error Handling + +All API errors extend `SmartyError`: + +```javascript +import { SmartyError } from "smartystreets-javascript-sdk"; + +try { + const response = await client.send(lookup); +} catch (err) { + if (err instanceof SmartyError) { + console.error("API error:", err.message); + } +} +``` + +### Retry and Timeout + +```javascript +const client = new SmartySDK.core.ClientBuilder(credentials) + .withMaxRetries(10) + .withMaxTimeout(30000) + .buildUsStreetApiClient(); +``` + +### Proxy + +```javascript +const client = new SmartySDK.core.ClientBuilder(credentials) + .withProxy("proxy.example.com", 8080, "https") + .buildUsStreetApiClient(); +``` + +### Custom Headers + +```javascript +const client = new SmartySDK.core.ClientBuilder(credentials) + .withCustomHeaders({ "X-Custom-Header": "value" }) + .buildUsStreetApiClient(); +``` + +## TypeScript + +The SDK is written in TypeScript and ships with full type declarations. All types are available as named exports: + +```typescript +import SmartySDK, { type MatchStrategy, type SmartyError } from "smartystreets-javascript-sdk"; + +const lookup = new SmartySDK.usStreet.Lookup(); +lookup.street = "1600 Amphitheatre Parkway"; +lookup.match = "enhanced" satisfies MatchStrategy; +``` + +## Documentation + +Full API documentation is available at [smarty.com/docs/sdk/javascript](https://www.smarty.com/docs/sdk/javascript). + +## License + +[Apache 2.0](LICENSE.md) diff --git a/Readme.md b/Readme.md deleted file mode 100644 index 48f33d0..0000000 --- a/Readme.md +++ /dev/null @@ -1,11 +0,0 @@ -#### SMARTY DISCLAIMER: Subject to the terms of the associated license agreement, this software is freely available for your use. This software is FREE, AS IN PUPPIES, and is a gift. Enjoy your new responsibility. This means that while we may consider enhancement requests, we may or may not choose to entertain requests at our sole and absolute discretion. - -# Smarty JavaScript SDK - -The official client libraries for accessing Smarty APIs with JavaScript. - -[![asciicast](https://asciinema.org/a/189101.png)](https://asciinema.org/a/189101) - -You may have noticed this page is curiously sparse. Don't panic, there's [documentation](https://www.smarty.com/docs/sdk/javascript) as well as working [examples](examples) over on our website. - -[Apache 2.0 License](LICENSE) diff --git a/examples/international_address_autocomplete.mjs b/examples/international_address_autocomplete.mjs index 2dbab98..494e564 100644 --- a/examples/international_address_autocomplete.mjs +++ b/examples/international_address_autocomplete.mjs @@ -24,19 +24,19 @@ const client = clientBuilder.buildInternationalAddressAutocompleteClient(); // www.smarty.com/docs/cloud/international-address-autocomplete-api#pro-http-request-input-fields const country = "CAN"; -const summaryLookup = new Lookup({search: "123 Anson", country}); +const summaryLookup = new Lookup({ search: "123 Anson", country }); // uncomment the following line to add a custom parameter // summaryLookup.addCustomParameter("max_results", 1); await handleRequest(summaryLookup, "Response of summary results"); -const detailedLookup = new Lookup({addressId: summaryLookup.result[0].addressId, country}); +const detailedLookup = new Lookup({ addressId: summaryLookup.result[0].addressId, country }); await handleRequest(detailedLookup, "Response using an address ID to get detailed results"); function logSuggestions(response, message) { console.log("*** " + message + " ***"); - response.result.forEach(suggestion => { + response.result.forEach((suggestion) => { if (suggestion.addressText) { console.log("Entries: ", suggestion.entries); console.log("Address Text: ", suggestion.addressText); @@ -56,7 +56,7 @@ async function handleRequest(lookup, lookupType) { try { const results = await client.send(lookup); logSuggestions(results, lookupType); - } catch(err) { - console.log(err) + } catch (err) { + console.log(err); } -} \ No newline at end of file +} diff --git a/examples/international_street.mjs b/examples/international_street.mjs index 1b37f6d..aa9463a 100644 --- a/examples/international_street.mjs +++ b/examples/international_street.mjs @@ -38,8 +38,8 @@ lookup2.administrativeArea = "SP"; lookup2.country = "Brazil"; lookup2.postalCode = "02516-050"; -await handleRequest(lookup1) -await handleRequest(lookup2) +await handleRequest(lookup1); +await handleRequest(lookup2); function displayResult(result) { console.log(result.result[0].components); @@ -53,7 +53,7 @@ async function handleRequest(lookup) { try { const result = await client.send(lookup); displayResult(result); - } catch(err) { + } catch (err) { handleError(err); } -} \ No newline at end of file +} diff --git a/examples/us_autocomplete_pro.mjs b/examples/us_autocomplete_pro.mjs index 19bf61a..46ec9c9 100644 --- a/examples/us_autocomplete_pro.mjs +++ b/examples/us_autocomplete_pro.mjs @@ -46,7 +46,7 @@ lookup = new Lookup("4770 Lincoln"); lookup.selected = "4770 N Lincoln Ave Ste 2 (3) Chicago, IL 60625"; -await handleRequest(lookup, "Using 'selected' to Expand Secondaries") +await handleRequest(lookup, "Using 'selected' to Expand Secondaries"); // ************************************************ @@ -60,7 +60,7 @@ async function handleRequest(lookup, lookupType) { try { const results = await client.send(lookup); logSuggestions(results, lookupType); - } catch(err) { - console.log(err) + } catch (err) { + console.log(err); } -} \ No newline at end of file +} diff --git a/examples/us_enrichment.mjs b/examples/us_enrichment.mjs index df918f7..708d11c 100644 --- a/examples/us_enrichment.mjs +++ b/examples/us_enrichment.mjs @@ -36,4 +36,4 @@ async function handleResponse(lookup) { } catch (err) { console.log(err); } -} \ No newline at end of file +} diff --git a/examples/us_extract.mjs b/examples/us_extract.mjs index 85f6405..bcb3e56 100644 --- a/examples/us_extract.mjs +++ b/examples/us_extract.mjs @@ -13,14 +13,16 @@ let authToken = process.env.SMARTY_AUTH_TOKEN; const credentials = new SmartyCore.BasicAuthCredentials(authId, authToken); let clientBuilder = new SmartyCore.ClientBuilder(credentials); - // .withBaseUrl("YOUR URL") // withBaseUrl() should be used if you are self-hosting the Smarty API +// .withBaseUrl("YOUR URL") // withBaseUrl() should be used if you are self-hosting the Smarty API let client = clientBuilder.buildUsExtractClient(); // Documentation for input fields can be found at: // https://www.smarty.com/docs/cloud/us-extract-api#http-request-input-fields -let lookup = new Lookup("If you work at 1600 Pennsylvania Ave NW, Washington DC you're gonna have a hard time."); +let lookup = new Lookup( + "If you work at 1600 Pennsylvania Ave NW, Washington DC you're gonna have a hard time.", +); lookup.aggressive = true; lookup.addressesHaveLineBreaks = false; lookup.addressesPerLine = 1; @@ -38,7 +40,7 @@ async function handleRequest(lookup) { try { const response = await client.send(lookup); logResult(response); - } catch(err) { + } catch (err) { console.log(err); } -} \ No newline at end of file +} diff --git a/examples/us_reverse_geo.mjs b/examples/us_reverse_geo.mjs index 8dcd519..1269a4b 100644 --- a/examples/us_reverse_geo.mjs +++ b/examples/us_reverse_geo.mjs @@ -37,7 +37,7 @@ async function handleResponse(lookup) { try { const result = await client.send(lookup); displayResult(result); - } catch(err) { + } catch (err) { handleError(err); } } diff --git a/index.mjs b/index.ts similarity index 86% rename from index.mjs rename to index.ts index c053a6c..cca3b77 100644 --- a/index.mjs +++ b/index.ts @@ -36,6 +36,13 @@ import ResponseUSEnrichment from "./src/us_enrichment/Response.js"; import LookupInternationalPostalCode from "./src/international_postal_code/Lookup.js"; import ResultInternationalPostalCode from "./src/international_postal_code/Result.js"; +export type { Request, Response, Sender, Sleeper, Signer } from "./src/types.js"; +export { SmartyError } from "./src/Errors.js"; +export type { MatchStrategy, OutputFormat, CountySource } from "./src/us_street/Lookup.js"; +export type { CoordinateLicense, MatchInfo } from "./src/us_street/Candidate.js"; +export type { Geolocation } from "./src/us_autocomplete_pro/Lookup.js"; +export type { Language, Geocode } from "./src/international_street/Lookup.js"; + export const core = { Batch, ClientBuilder, diff --git a/package.json b/package.json index b182ce0..a73b6d9 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ ], "files": [ "dist", - "README.md", + "README.md", "LICENSE" ], "main": "dist/cjs/index.cjs", @@ -31,6 +31,7 @@ "types": "dist/types/index.d.ts", "exports": { ".": { + "types": "./dist/types/index.d.ts", "import": "./dist/esm/index.mjs", "default": "./dist/cjs/index.cjs" } @@ -41,9 +42,7 @@ }, "scripts": { "build": "rollup --config", - "test": "npm run test:js && npm run test:ts", - "test:js": "mocha 'tests/**/*.{mjs,js}'", - "test:ts": "mocha --require tsx/cjs 'tests/**/*.ts'" + "test": "mocha --require tsx/cjs 'tests/**/*.ts'" }, "author": "Smarty SDK Team (https://www.smarty.com)", "license": "Apache-2.0", diff --git a/rollup.config.mjs b/rollup.config.mjs index cef8d6c..afd4b2d 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -6,43 +6,43 @@ import { nodeResolve } from "@rollup/plugin-node-resolve"; import typescript from "@rollup/plugin-typescript"; export default { - input: "index.mjs", - external: ["axios", "axios-retry"], - output: [ - { - dir: "dist", - format: "esm", - preserveModules: true, - preserveModulesRoot: "src", - exports: "named", - entryFileNames: "esm/[name].mjs", - }, - { - dir: "dist", - format: "cjs", - preserveModules: true, - preserveModulesRoot: "src", - exports: "named", - esModule: false, - entryFileNames: "cjs/[name].cjs", - }, - ], - plugins: [ - del({ targets: "dist/*" }), - nodeResolve(), - commonjs({ - esmExternals: true, - requireReturnsDefault: true, - }), - json(), - terser(), - typescript({ - declaration: true, - emitDeclarationOnly: true, - outDir: "dist/types", - rootDir: "src", - importHelpers: false, - target: "es2015", - }), - ], -}; \ No newline at end of file + input: "index.ts", + external: ["axios", "axios-retry"], + output: [ + { + dir: "dist", + format: "esm", + preserveModules: true, + preserveModulesRoot: "src", + exports: "named", + entryFileNames: "esm/[name].mjs", + }, + { + dir: "dist", + format: "cjs", + preserveModules: true, + preserveModulesRoot: "src", + exports: "named", + esModule: false, + entryFileNames: "cjs/[name].cjs", + }, + ], + plugins: [ + del({ targets: "dist/*" }), + nodeResolve(), + commonjs({ + esmExternals: true, + requireReturnsDefault: true, + }), + json(), + terser(), + typescript({ + declaration: true, + emitDeclarationOnly: true, + outDir: "dist/types", + rootDir: ".", + importHelpers: false, + target: "es2015", + }), + ], +}; diff --git a/src/AgentSender.ts b/src/AgentSender.ts index 872efa4..4b223a4 100644 --- a/src/AgentSender.ts +++ b/src/AgentSender.ts @@ -9,10 +9,7 @@ export default class AgentSender { } send(request: Request): Promise { - request.parameters["agent"] = - "smarty (sdk:javascript@" + packageJson.version + ")"; - return new Promise((resolve, reject) => { - this.sender.send(request).then(resolve).catch(reject); - }); + request.parameters["agent"] = "smarty (sdk:javascript@" + packageJson.version + ")"; + return this.sender.send(request); } } diff --git a/src/BaseUrlSender.ts b/src/BaseUrlSender.ts index d17ebc1..ccf10b4 100644 --- a/src/BaseUrlSender.ts +++ b/src/BaseUrlSender.ts @@ -10,12 +10,10 @@ export default class BaseUrlSender { } send(request: Request): Promise { - return new Promise((resolve, reject) => { - request.baseUrl = `${this.urlOverride}${ - request.baseUrlParam ? `/${request.baseUrlParam}` : "" - }`; + request.baseUrl = `${this.urlOverride}${ + request.baseUrlParam ? `/${request.baseUrlParam}` : "" + }`; - this.sender.send(request).then(resolve).catch(reject); - }); + return this.sender.send(request); } } diff --git a/src/Batch.js b/src/Batch.js deleted file mode 100644 index ccc00f7..0000000 --- a/src/Batch.js +++ /dev/null @@ -1,49 +0,0 @@ -const BatchFullError = require("./Errors").BatchFullError; - -/** - * This class contains a collection of up to 100 lookups to be sent to one of the Smarty APIs
- * all at once. This is more efficient than sending them one at a time. - */ -class Batch { - constructor () { - this.lookups = []; - } - - add (lookup) { - if (this.lookupsHasRoomForLookup()) this.lookups.push(lookup); - else throw new BatchFullError(); - } - - lookupsHasRoomForLookup() { - const maxNumberOfLookups = 100; - return this.lookups.length < maxNumberOfLookups; - } - - length() { - return this.lookups.length; - } - - getByIndex(index) { - return this.lookups[index]; - } - - getByInputId(inputId) { - return this.lookups.filter(lookup => { - return lookup.inputId === inputId; - })[0]; - } - - /** - * Clears the lookups stored in the batch so it can be used again.
- * This helps avoid the overhead of building a new Batch object for each group of lookups. - */ - clear () { - this.lookups = []; - } - - isEmpty () { - return this.length() === 0; - } -} - -module.exports = Batch; \ No newline at end of file diff --git a/src/Batch.ts b/src/Batch.ts new file mode 100644 index 0000000..a64354a --- /dev/null +++ b/src/Batch.ts @@ -0,0 +1,42 @@ +import { BatchFullError } from "./Errors.js"; +import { BaseLookup } from "./types.js"; + +export default class Batch { + lookups: BaseLookup[]; + + constructor() { + this.lookups = []; + } + + add(lookup: BaseLookup): void { + if (this.lookupsHasRoomForLookup()) this.lookups.push(lookup); + else throw new BatchFullError(); + } + + lookupsHasRoomForLookup(): boolean { + const maxNumberOfLookups = 100; + return this.lookups.length < maxNumberOfLookups; + } + + length(): number { + return this.lookups.length; + } + + getByIndex(index: number): BaseLookup { + return this.lookups[index]; + } + + getByInputId(inputId: string | number): BaseLookup | undefined { + return this.lookups.filter((lookup) => { + return lookup.inputId === inputId; + })[0]; + } + + clear(): void { + this.lookups = []; + } + + isEmpty(): boolean { + return this.length() === 0; + } +} diff --git a/src/ClientBuilder.js b/src/ClientBuilder.js deleted file mode 100644 index 8fa8b37..0000000 --- a/src/ClientBuilder.js +++ /dev/null @@ -1,299 +0,0 @@ -const HttpSender = require("./HttpSender"); -const SigningSender = require("./SigningSender"); -const BaseUrlSender = require("./BaseUrlSender"); -const AgentSender = require("./AgentSender"); -const StaticCredentials = require("./StaticCredentials"); -const SharedCredentials = require("./SharedCredentials"); -const BasicAuthCredentials = require("./BasicAuthCredentials"); -const CustomHeaderSender = require("./CustomHeaderSender"); -const StatusCodeSender = require("./StatusCodeSender"); -const LicenseSender = require("./LicenseSender"); -const CustomQuerySender = require("@/src/CustomQuerySender"); -const BadCredentialsError = require("./Errors").BadCredentialsError; -const RetrySender = require("./RetrySender"); -const Sleeper = require("./util/Sleeper.ts"); - -//TODO: refactor this to work more cleanly with a bundler. -const UsStreetClient = require("./us_street/Client"); -const UsZipcodeClient = require("./us_zipcode/Client"); -const UsAutocompleteProClient = require("./us_autocomplete_pro/Client"); -const UsExtractClient = require("./us_extract/Client"); -const InternationalStreetClient = require("./international_street/Client"); -const UsReverseGeoClient = require("./us_reverse_geo/Client"); -const InternationalAddressAutocompleteClient = require("./international_address_autocomplete/Client"); -const UsEnrichmentClient = require("./us_enrichment/Client"); -const InternationalPostalCodeClient = require("./international_postal_code/Client"); - -const INTERNATIONAL_STREET_API_URI = "https://international-street.api.smarty.com/verify"; -const US_AUTOCOMPLETE_PRO_API_URL = "https://us-autocomplete-pro.api.smarty.com/lookup"; -const US_EXTRACT_API_URL = "https://us-extract.api.smarty.com/"; -const US_STREET_API_URL = "https://us-street.api.smarty.com/street-address"; -const US_ZIP_CODE_API_URL = "https://us-zipcode.api.smarty.com/lookup"; -const US_REVERSE_GEO_API_URL = "https://us-reverse-geo.api.smarty.com/lookup"; -const INTERNATIONAL_ADDRESS_AUTOCOMPLETE_API_URL = - "https://international-autocomplete.api.smarty.com/v2/lookup"; -const US_ENRICHMENT_API_URL = "https://us-enrichment.api.smarty.com/lookup"; -const INTERNATIONAL_POSTAL_CODE_API_URL = "https://international-postal-code.api.smarty.com/lookup"; -/** - * The ClientBuilder class helps you build a client object for one of the supported Smarty APIs.
- * You can use ClientBuilder's methods to customize settings like maximum retries or timeout duration. These methods
- * are chainable, so you can usually get set up with one line of code. - */ -class ClientBuilder { - constructor(signer) { - if (!credentialsProvided()) throw new BadCredentialsError(); - - this.signer = signer; - this.httpSender = undefined; - this.maxRetries = 5; - this.maxTimeout = 10000; - this.baseUrl = undefined; - this.proxy = undefined; - this.customHeaders = {}; - this.appendHeaders = {}; - this.debug = undefined; - this.licenses = []; - this.customQueries = new Map(); - - function credentialsProvided() { - return signer instanceof StaticCredentials || signer instanceof SharedCredentials || signer instanceof BasicAuthCredentials; - } - } - - /** - * @param retries The maximum number of times to retry sending the request to the API. (Default is 5) - * @return ClientBuilder this to accommodate method chaining. - */ - withMaxRetries(retries) { - this.maxRetries = retries; - return this; - } - - /** - * @param timeout The maximum time (in milliseconds) to wait for a connection, and also to wait for
- * the response to be read. (Default is 10000) - * @return ClientBuilder this to accommodate method chaining. - */ - withMaxTimeout(timeout) { - this.maxTimeout = timeout; - return this; - } - - /** - * @param sender Default is a series of nested senders. See buildSender(). - * @return ClientBuilder this to accommodate method chaining. - */ - withSender(sender) { - this.httpSender = sender; - return this; - } - - /** - * This may be useful when using a local installation of the Smarty APIs. - * @param url Defaults to the URL for the API corresponding to the Client object being built. - * @return ClientBuilder this to accommodate method chaining. - */ - withBaseUrl(url) { - this.baseUrl = url; - return this; - } - - /** - * Use this to specify a proxy through which to send all lookups. - * @param host The host of the proxy server (do not include the port). - * @param port The port on the proxy server to which you wish to connect. - * @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'. - * @param username The username to login to the proxy. - * @param password The password to login to the proxy. - * @return ClientBuilder this to accommodate method chaining. - */ - withProxy(host, port, protocol, username, password) { - this.proxy = { - host: host, - port: port, - protocol: protocol, - }; - - if (username && password) { - this.proxy.auth = { - username: username, - password: password, - }; - } - - return this; - } - - /** - * Use this to add any additional headers you need. - * @param customHeaders A String to Object Map of header name/value pairs. - * @return ClientBuilder this to accommodate method chaining. - */ - withCustomHeaders(customHeaders) { - this.customHeaders = customHeaders; - return this; - } - - /** - * Appends the provided value to the existing header value using the specified separator, - * rather than replacing it. This is useful for single-value headers like User-Agent. - * @param key The header name. - * @param value The value to append. - * @param separator The separator to use when joining values. - * @return ClientBuilder this to accommodate method chaining. - */ - withAppendedHeader(key, value, separator) { - if (this.appendHeaders[key]) { - if (this.appendHeaders[key].separator !== separator) { - throw new Error( - `Conflicting separators for appended header "${key}": ` + - `existing "${this.appendHeaders[key].separator}" vs new "${separator}"`, - ); - } - this.appendHeaders[key].values.push(value); - } else { - this.appendHeaders[key] = { values: [value], separator }; - } - return this; - } - - /** - * Enables debug mode, which will print information about the HTTP request and response to console.log - * @return ClientBuilder this to accommodate method chaining. - */ - withDebug() { - this.debug = true; - return this; - } - - /** - * Allows the caller to specify the subscription license (aka "track") they wish to use. - * @param licenses A String Array of licenses. - * @returns ClientBuilder this to accommodate method chaining. - */ - withLicenses(licenses) { - this.licenses = licenses; - return this; - } - - /** - * Allows the caller to specify key and value pair that is added to the request - * @param {string} key - The query parameter key - * @param {string} value - The query parameter value - * @return ClientBuilder this to accommodate method chaining. - */ - withCustomQuery(key, value) { - this.customQueries.set(key, value); - return this; - } - - /** - * Allows the caller to specify key and value pair and appends the value associated with the key, seperated by a comma. - * @param {string} key - The query parameter key - * @param {string} value - The query parameter value - * @return ClientBuilder this to accommodate method chaining. - */ - withCustomCommaSeperatedQuery(key, value) { - let values = this.customQueries.get(key); - if (values === "") { - values = value; - } else { - values += "," + value; - } - this.customQueries.set(key, values); - return this; - } - - /** - * Adds to the request query to use the component analysis feature. - * @return ClientBuilder this to accommodate method chaining. - */ - withFeatureComponentAnalysis() { - return this.withCustomCommaSeperatedQuery("features", "component-analysis"); - } - - /** - * Adds to the request query to use the financial history feature. - * @return ClientBuilder this to accommodate method chaining. - */ - withFinancialHistory() { - return this.withCustomCommaSeperatedQuery("features", "financial"); - } - - /** - * Adds to the request query to use the occupant use feature. - * @return ClientBuilder this to accommodate method chaining. - */ - withOccupantUse() { - return this.withCustomCommaSeperatedQuery("features", "occupant-use"); - } - - - buildSender() { - if (this.httpSender) return this.httpSender; - - const httpSender = new HttpSender(this.maxTimeout, this.proxy, this.debug); - const statusCodeSender = new StatusCodeSender(httpSender); - const signingSender = new SigningSender(statusCodeSender, this.signer); - let agentSender = new AgentSender(signingSender); - if (this.maxRetries > 0) { - const retrySender = new RetrySender(this.maxRetries, signingSender, new Sleeper()); - agentSender = new AgentSender(retrySender); - } - const customHeaderSender = new CustomHeaderSender(agentSender, this.customHeaders, this.appendHeaders); - const baseUrlSender = new BaseUrlSender(customHeaderSender, this.baseUrl); - const licenseSender = new LicenseSender(baseUrlSender, this.licenses); - const customQuerySender = new CustomQuerySender(licenseSender, this.customQueries); - - return customQuerySender; - } - - buildClient(baseUrl, Client) { - if (!this.baseUrl) { - this.baseUrl = baseUrl; - } - - return new Client(this.buildSender()); - } - - buildUsStreetApiClient() { - return this.buildClient(US_STREET_API_URL, UsStreetClient); - } - - buildUsZipcodeClient() { - return this.buildClient(US_ZIP_CODE_API_URL, UsZipcodeClient); - } - - buildInternationalPostalCodeClient() { - return this.buildClient(INTERNATIONAL_POSTAL_CODE_API_URL, InternationalPostalCodeClient); - } - - buildUsAutocompleteProClient() { - return this.buildClient(US_AUTOCOMPLETE_PRO_API_URL, UsAutocompleteProClient); - } - - buildUsExtractClient() { - return this.buildClient(US_EXTRACT_API_URL, UsExtractClient); - } - - buildInternationalStreetClient() { - return this.buildClient(INTERNATIONAL_STREET_API_URI, InternationalStreetClient); - } - - buildUsReverseGeoClient() { - return this.buildClient(US_REVERSE_GEO_API_URL, UsReverseGeoClient); - } - - buildInternationalAddressAutocompleteClient() { - return this.buildClient( - INTERNATIONAL_ADDRESS_AUTOCOMPLETE_API_URL, - InternationalAddressAutocompleteClient, - ); - } - - buildUsEnrichmentClient() { - return this.buildClient(US_ENRICHMENT_API_URL, UsEnrichmentClient); - } -} - -module.exports = ClientBuilder; diff --git a/src/ClientBuilder.ts b/src/ClientBuilder.ts new file mode 100644 index 0000000..4153af9 --- /dev/null +++ b/src/ClientBuilder.ts @@ -0,0 +1,246 @@ +import HttpSender from "./HttpSender.js"; +import SigningSender from "./SigningSender.js"; +import BaseUrlSender from "./BaseUrlSender.js"; +import AgentSender from "./AgentSender.js"; +import StaticCredentials from "./StaticCredentials.js"; +import SharedCredentials from "./SharedCredentials.js"; +import BasicAuthCredentials from "./BasicAuthCredentials.js"; +import CustomHeaderSender, { AppendHeader } from "./CustomHeaderSender.js"; +import StatusCodeSender from "./StatusCodeSender.js"; +import LicenseSender from "./LicenseSender.js"; +import CustomQuerySender from "./CustomQuerySender.js"; +import { BadCredentialsError } from "./Errors.js"; +import RetrySender from "./RetrySender.js"; +import Sleeper from "./util/Sleeper.js"; + +import UsStreetClient from "./us_street/Client.js"; +import UsZipcodeClient from "./us_zipcode/Client.js"; +import UsAutocompleteProClient from "./us_autocomplete_pro/Client.js"; +import UsExtractClient from "./us_extract/Client.js"; +import InternationalStreetClient from "./international_street/Client.js"; +import UsReverseGeoClient from "./us_reverse_geo/Client.js"; +import InternationalAddressAutocompleteClient from "./international_address_autocomplete/Client.js"; +import UsEnrichmentClient from "./us_enrichment/Client.js"; +import InternationalPostalCodeClient from "./international_postal_code/Client.js"; +import { Sender } from "./types.js"; +import { AxiosProxyConfig } from "axios"; + +const INTERNATIONAL_STREET_API_URI = "https://international-street.api.smarty.com/verify"; +const US_AUTOCOMPLETE_PRO_API_URL = "https://us-autocomplete-pro.api.smarty.com/lookup"; +const US_EXTRACT_API_URL = "https://us-extract.api.smarty.com/"; +const US_STREET_API_URL = "https://us-street.api.smarty.com/street-address"; +const US_ZIP_CODE_API_URL = "https://us-zipcode.api.smarty.com/lookup"; +const US_REVERSE_GEO_API_URL = "https://us-reverse-geo.api.smarty.com/lookup"; +const INTERNATIONAL_ADDRESS_AUTOCOMPLETE_API_URL = + "https://international-autocomplete.api.smarty.com/v2/lookup"; +const US_ENRICHMENT_API_URL = "https://us-enrichment.api.smarty.com/lookup"; +const INTERNATIONAL_POSTAL_CODE_API_URL = "https://international-postal-code.api.smarty.com/lookup"; + +type Signer = StaticCredentials | SharedCredentials | BasicAuthCredentials; + +export default class ClientBuilder { + private signer: Signer; + private httpSender: Sender | undefined; + private maxRetries: number; + private maxTimeout: number; + private baseUrl: string | undefined; + private proxy: AxiosProxyConfig | undefined; + private customHeaders: Record; + private appendHeaders: Record; + private debug: boolean | undefined; + private licenses: string[]; + private customQueries: Map; + + constructor(signer: Signer) { + if ( + !( + signer instanceof StaticCredentials || + signer instanceof SharedCredentials || + signer instanceof BasicAuthCredentials + ) + ) + throw new BadCredentialsError(); + + this.signer = signer; + this.httpSender = undefined; + this.maxRetries = 5; + this.maxTimeout = 10000; + this.baseUrl = undefined; + this.proxy = undefined; + this.customHeaders = {}; + this.appendHeaders = {}; + this.debug = undefined; + this.licenses = []; + this.customQueries = new Map(); + } + + withMaxRetries(retries: number): ClientBuilder { + this.maxRetries = retries; + return this; + } + + withMaxTimeout(timeout: number): ClientBuilder { + this.maxTimeout = timeout; + return this; + } + + withSender(sender: Sender): ClientBuilder { + this.httpSender = sender; + return this; + } + + withBaseUrl(url: string): ClientBuilder { + this.baseUrl = url; + return this; + } + + withProxy( + host: string, + port: number, + protocol: string, + username?: string, + password?: string, + ): ClientBuilder { + this.proxy = { + host: host, + port: port, + protocol: protocol, + }; + + if (username && password) { + this.proxy.auth = { + username: username, + password: password, + }; + } + + return this; + } + + withCustomHeaders(customHeaders: Record): ClientBuilder { + this.customHeaders = customHeaders; + return this; + } + + withAppendedHeader(key: string, value: string, separator: string): ClientBuilder { + if (this.appendHeaders[key]) { + if (this.appendHeaders[key].separator !== separator) { + throw new Error( + `Conflicting separators for appended header "${key}": ` + + `existing "${this.appendHeaders[key].separator}" vs new "${separator}"`, + ); + } + this.appendHeaders[key].values.push(value); + } else { + this.appendHeaders[key] = { values: [value], separator }; + } + return this; + } + + withDebug(): ClientBuilder { + this.debug = true; + return this; + } + + withLicenses(licenses: string[]): ClientBuilder { + this.licenses = licenses; + return this; + } + + withCustomQuery(key: string, value: string): ClientBuilder { + this.customQueries.set(key, value); + return this; + } + + withCustomCommaSeperatedQuery(key: string, value: string): ClientBuilder { + const values = this.customQueries.get(key); + if (values === undefined) { + this.customQueries.set(key, value); + } else { + this.customQueries.set(key, values + "," + value); + } + return this; + } + + withFeatureComponentAnalysis(): ClientBuilder { + return this.withCustomCommaSeperatedQuery("features", "component-analysis"); + } + + withFinancialHistory(): ClientBuilder { + return this.withCustomCommaSeperatedQuery("features", "financial"); + } + + withOccupantUse(): ClientBuilder { + return this.withCustomCommaSeperatedQuery("features", "occupant-use"); + } + + buildSender(): Sender { + if (this.httpSender) return this.httpSender; + + const httpSender = new HttpSender(this.maxTimeout, this.proxy, this.debug); + const statusCodeSender = new StatusCodeSender(httpSender); + const signingSender = new SigningSender(statusCodeSender, this.signer); + let agentSender = new AgentSender(signingSender); + if (this.maxRetries > 0) { + const retrySender = new RetrySender(this.maxRetries, signingSender, new Sleeper()); + agentSender = new AgentSender(retrySender); + } + const customHeaderSender = new CustomHeaderSender( + agentSender, + this.customHeaders, + this.appendHeaders, + ); + const baseUrlSender = new BaseUrlSender(customHeaderSender, this.baseUrl!); + const licenseSender = new LicenseSender(baseUrlSender, this.licenses); + const customQuerySender = new CustomQuerySender(licenseSender, this.customQueries); + + return customQuerySender; + } + + buildClient(baseUrl: string, ClientClass: new (sender: Sender) => T): T { + if (!this.baseUrl) { + this.baseUrl = baseUrl; + } + + return new ClientClass(this.buildSender()); + } + + buildUsStreetApiClient(): UsStreetClient { + return this.buildClient(US_STREET_API_URL, UsStreetClient); + } + + buildUsZipcodeClient(): UsZipcodeClient { + return this.buildClient(US_ZIP_CODE_API_URL, UsZipcodeClient); + } + + buildInternationalPostalCodeClient(): InternationalPostalCodeClient { + return this.buildClient(INTERNATIONAL_POSTAL_CODE_API_URL, InternationalPostalCodeClient); + } + + buildUsAutocompleteProClient(): UsAutocompleteProClient { + return this.buildClient(US_AUTOCOMPLETE_PRO_API_URL, UsAutocompleteProClient); + } + + buildUsExtractClient(): UsExtractClient { + return this.buildClient(US_EXTRACT_API_URL, UsExtractClient); + } + + buildInternationalStreetClient(): InternationalStreetClient { + return this.buildClient(INTERNATIONAL_STREET_API_URI, InternationalStreetClient); + } + + buildUsReverseGeoClient(): UsReverseGeoClient { + return this.buildClient(US_REVERSE_GEO_API_URL, UsReverseGeoClient); + } + + buildInternationalAddressAutocompleteClient(): InternationalAddressAutocompleteClient { + return this.buildClient( + INTERNATIONAL_ADDRESS_AUTOCOMPLETE_API_URL, + InternationalAddressAutocompleteClient, + ); + } + + buildUsEnrichmentClient(): UsEnrichmentClient { + return this.buildClient(US_ENRICHMENT_API_URL, UsEnrichmentClient); + } +} diff --git a/src/CustomHeaderSender.ts b/src/CustomHeaderSender.ts index 5609740..7894ade 100644 --- a/src/CustomHeaderSender.ts +++ b/src/CustomHeaderSender.ts @@ -37,8 +37,6 @@ export default class CustomHeaderSender { } } - return new Promise((resolve, reject) => { - this.sender.send(request).then(resolve).catch(reject); - }); + return this.sender.send(request); } } diff --git a/src/Errors.js b/src/Errors.js deleted file mode 100644 index 9a79dac..0000000 --- a/src/Errors.js +++ /dev/null @@ -1,100 +0,0 @@ -class SmartyError extends Error { - constructor(message = "unexpected error") { - super(message); - } -} - -class DefaultError extends SmartyError { - constructor(message) { - super(message); - } - -} - -class BatchFullError extends SmartyError { - constructor() { - super("A batch can contain a max of 100 lookups."); - } -} - -class BatchEmptyError extends SmartyError { - constructor() { - super("A batch must contain at least 1 lookup."); - } -} - -class UndefinedLookupError extends SmartyError { - constructor() { - super("The lookup provided is missing or undefined. Make sure you're passing a Lookup object."); - } -} - -class BadCredentialsError extends SmartyError { - constructor() { - super("Unauthorized: The credentials were provided incorrectly or did not match any existing active credentials."); - } -} - -class PaymentRequiredError extends SmartyError { - constructor() { - super("Payment Required: There is no active subscription for the account associated with the credentials submitted with the request."); - } -} - -class RequestEntityTooLargeError extends SmartyError { - constructor() { - super("Request Entity Too Large: The request body has exceeded the maximum size."); - } -} - -class BadRequestError extends SmartyError { - constructor() { - super("Bad Request (Malformed Payload): A GET request lacked a street field or the request body of a POST request contained malformed JSON."); - } -} - -class UnprocessableEntityError extends SmartyError { - constructor(message) { - super(message); - } -} - -class TooManyRequestsError extends SmartyError { - constructor() { - super("When using the public 'embedded key' authentication, we restrict the number of requests coming from a given source over too short of a time."); - } -} - -class InternalServerError extends SmartyError { - constructor() { - super("Internal Server Error."); - } -} - -class ServiceUnavailableError extends SmartyError { - constructor() { - super("Service Unavailable. Try again later."); - } -} - -class GatewayTimeoutError extends SmartyError { - constructor() { - super("The upstream data provider did not respond in a timely fashion and the request failed. A serious, yet rare occurrence indeed."); - } -} - -module.exports = { - BatchFullError: BatchFullError, - BatchEmptyError: BatchEmptyError, - UndefinedLookupError: UndefinedLookupError, - BadCredentialsError: BadCredentialsError, - PaymentRequiredError: PaymentRequiredError, - RequestEntityTooLargeError: RequestEntityTooLargeError, - BadRequestError: BadRequestError, - UnprocessableEntityError: UnprocessableEntityError, - TooManyRequestsError: TooManyRequestsError, - InternalServerError: InternalServerError, - ServiceUnavailableError: ServiceUnavailableError, - GatewayTimeoutError: GatewayTimeoutError, - DefaultError: DefaultError -}; \ No newline at end of file diff --git a/src/Errors.ts b/src/Errors.ts new file mode 100644 index 0000000..28cb045 --- /dev/null +++ b/src/Errors.ts @@ -0,0 +1,110 @@ +export class SmartyError extends Error { + constructor(message: string = "unexpected error") { + super(message); + } +} + +export class DefaultError extends SmartyError { + constructor(message?: string | null) { + super(message || "unexpected error"); + } +} + +export class BatchFullError extends SmartyError { + constructor() { + super("A batch can contain a max of 100 lookups."); + } +} + +export class BatchEmptyError extends SmartyError { + constructor() { + super("A batch must contain at least 1 lookup."); + } +} + +export class UndefinedLookupError extends SmartyError { + constructor() { + super("The lookup provided is missing or undefined. Make sure you're passing a Lookup object."); + } +} + +export class BadCredentialsError extends SmartyError { + constructor() { + super( + "Unauthorized: The credentials were provided incorrectly or did not match any existing active credentials.", + ); + } +} + +export class PaymentRequiredError extends SmartyError { + constructor() { + super( + "Payment Required: There is no active subscription for the account associated with the credentials submitted with the request.", + ); + } +} + +export class RequestEntityTooLargeError extends SmartyError { + constructor() { + super("Request Entity Too Large: The request body has exceeded the maximum size."); + } +} + +export class BadRequestError extends SmartyError { + constructor() { + super( + "Bad Request (Malformed Payload): A GET request lacked a street field or the request body of a POST request contained malformed JSON.", + ); + } +} + +export class UnprocessableEntityError extends SmartyError { + constructor(message: string) { + super(message); + } +} + +export class TooManyRequestsError extends SmartyError { + constructor() { + super( + "When using the public 'embedded key' authentication, we restrict the number of requests coming from a given source over too short of a time.", + ); + } +} + +export class InternalServerError extends SmartyError { + constructor() { + super("Internal Server Error."); + } +} + +export class ServiceUnavailableError extends SmartyError { + constructor() { + super("Service Unavailable. Try again later."); + } +} + +export class GatewayTimeoutError extends SmartyError { + constructor() { + super( + "The upstream data provider did not respond in a timely fashion and the request failed. A serious, yet rare occurrence indeed.", + ); + } +} + +export default { + SmartyError, + BatchFullError, + BatchEmptyError, + UndefinedLookupError, + BadCredentialsError, + PaymentRequiredError, + RequestEntityTooLargeError, + BadRequestError, + UnprocessableEntityError, + TooManyRequestsError, + InternalServerError, + ServiceUnavailableError, + GatewayTimeoutError, + DefaultError, +}; diff --git a/src/HttpSender.js b/src/HttpSender.js deleted file mode 100644 index f488473..0000000 --- a/src/HttpSender.js +++ /dev/null @@ -1,66 +0,0 @@ -const Axios = require("axios"); -const {buildSmartyResponse} = require("../src/util/buildSmartyResponse"); - -class HttpSender { - constructor(timeout = 10000, proxyConfig, debug = false) { - this.axiosInstance = Axios.create(); - this.timeout = timeout; - this.proxyConfig = proxyConfig; - if (debug) this.enableDebug(); - } - - buildRequestConfig({payload, parameters, headers, baseUrl}) { - let config = { - method: "GET", - timeout: this.timeout, - params: parameters, - headers: headers, - baseURL: baseUrl, - validateStatus: function (status) { - return status < 500; - }, - }; - - if (payload) { - config.method = "POST"; - config.data = payload; - } - - if (this.proxyConfig) config.proxy = this.proxyConfig; - return config; - } - - send(request) { - return new Promise((resolve, reject) => { - let requestConfig = this.buildRequestConfig(request); - - this.axiosInstance(requestConfig) - .then(response => { - let smartyResponse = buildSmartyResponse(response); - - if (smartyResponse.statusCode >= 400) reject(smartyResponse); - - resolve(smartyResponse); - }) - .catch(error => reject(buildSmartyResponse(undefined, error))); - }); - } - - enableDebug() { - this.axiosInstance.interceptors.request.use(request => { - console.log('Request:\r\n', request); - console.log('\r\n*******************************************\r\n'); - return request - }); - - this.axiosInstance.interceptors.response.use(response => { - console.log('Response:\r\n'); - console.log('Status:', response.status, response.statusText); - console.log('Headers:', response.headers); - console.log('Data:', response.data); - return response - }) - } -} - -module.exports = HttpSender; \ No newline at end of file diff --git a/src/HttpSender.ts b/src/HttpSender.ts new file mode 100644 index 0000000..901e8dd --- /dev/null +++ b/src/HttpSender.ts @@ -0,0 +1,69 @@ +import Axios, { AxiosInstance, AxiosProxyConfig, AxiosRequestConfig } from "axios"; +import { buildSmartyResponse } from "./util/buildSmartyResponse.js"; +import { Request as SmartyRequest, Response as SmartyResponse } from "./types.js"; + +export default class HttpSender { + private axiosInstance: AxiosInstance; + private timeout: number; + private proxyConfig: AxiosProxyConfig | undefined; + + constructor(timeout: number = 10000, proxyConfig?: AxiosProxyConfig, debug: boolean = false) { + this.axiosInstance = Axios.create(); + this.timeout = timeout; + this.proxyConfig = proxyConfig; + if (debug) this.enableDebug(); + } + + buildRequestConfig(request: SmartyRequest): AxiosRequestConfig { + const config: AxiosRequestConfig = { + method: "GET", + timeout: this.timeout, + params: request.parameters, + headers: request.headers, + baseURL: request.baseUrl, + validateStatus: function (status: number) { + return status < 500; + }, + }; + + if (request.payload) { + config.method = "POST"; + config.data = request.payload; + } + + if (this.proxyConfig) config.proxy = this.proxyConfig; + return config; + } + + send(request: SmartyRequest): Promise { + return new Promise((resolve, reject) => { + const requestConfig = this.buildRequestConfig(request); + + this.axiosInstance(requestConfig) + .then((response) => { + const smartyResponse = buildSmartyResponse(response); + + if (smartyResponse.statusCode >= 400) return reject(smartyResponse); + + resolve(smartyResponse); + }) + .catch((error) => reject(buildSmartyResponse(undefined, error))); + }); + } + + private enableDebug(): void { + this.axiosInstance.interceptors.request.use((request) => { + console.log("Request:\r\n", request); + console.log("\r\n*******************************************\r\n"); + return request; + }); + + this.axiosInstance.interceptors.response.use((response) => { + console.log("Response:\r\n"); + console.log("Status:", response.status, response.statusText); + console.log("Headers:", response.headers); + console.log("Data:", response.data); + return response; + }); + } +} diff --git a/src/InputData.js b/src/InputData.js deleted file mode 100644 index 1115738..0000000 --- a/src/InputData.js +++ /dev/null @@ -1,25 +0,0 @@ -class InputData { - constructor(lookup) { - this.lookup = lookup; - this.data = {}; - } - - add(apiField, lookupField) { - if (this.lookupFieldIsPopulated(lookupField)) this.data[apiField] = this.formatData(this.lookup[lookupField]); - } - - addCustomParameter(key, value) { - this.data[key] = value; - } - - formatData(field) { - if (Array.isArray(field)) return field.join(";"); - else return field; - } - - lookupFieldIsPopulated(lookupField) { - return this.lookup[lookupField] !== "" && this.lookup[lookupField] !== undefined; - } -} - -module.exports = InputData; \ No newline at end of file diff --git a/src/InputData.ts b/src/InputData.ts new file mode 100644 index 0000000..38af92f --- /dev/null +++ b/src/InputData.ts @@ -0,0 +1,27 @@ +export default class InputData { + lookup: Record; + data: Record; + + constructor(lookup: Record) { + this.lookup = lookup; + this.data = {}; + } + + add(apiField: string, lookupField: string): void { + if (this.lookupFieldIsPopulated(lookupField)) + this.data[apiField] = this.formatData(this.lookup[lookupField]); + } + + addCustomParameter(key: string, value: string): void { + this.data[key] = value; + } + + formatData(field: string | number | string[]): string | number { + if (Array.isArray(field)) return field.join(";"); + return field; + } + + lookupFieldIsPopulated(lookupField: string): boolean { + return this.lookup[lookupField] !== "" && this.lookup[lookupField] !== undefined; + } +} diff --git a/src/LicenseSender.js b/src/LicenseSender.js deleted file mode 100644 index dd6189f..0000000 --- a/src/LicenseSender.js +++ /dev/null @@ -1,20 +0,0 @@ -class LicenseSender { - constructor(innerSender, licenses) { - this.sender = innerSender; - this.licenses = licenses; - } - - send(request) { - if (this.licenses.length !== 0) { - request.parameters["license"] = this.licenses.join(","); - } - - return new Promise((resolve, reject) => { - this.sender.send(request) - .then(resolve) - .catch(reject); - }); - } -} - -module.exports = LicenseSender; \ No newline at end of file diff --git a/src/LicenseSender.ts b/src/LicenseSender.ts new file mode 100644 index 0000000..37e3212 --- /dev/null +++ b/src/LicenseSender.ts @@ -0,0 +1,19 @@ +import { Request, Response, Sender } from "./types.js"; + +export default class LicenseSender { + private sender: Sender; + private licenses: string[]; + + constructor(innerSender: Sender, licenses: string[]) { + this.sender = innerSender; + this.licenses = licenses; + } + + send(request: Request): Promise { + if (this.licenses.length !== 0) { + request.parameters["license"] = this.licenses.join(","); + } + + return this.sender.send(request); + } +} diff --git a/src/Request.js b/src/Request.js deleted file mode 100644 index 59294a2..0000000 --- a/src/Request.js +++ /dev/null @@ -1,12 +0,0 @@ -class Request { - constructor(payload, headers = {"Content-Type": "application/json; charset=utf-8"}) { - this.baseUrl = ""; - this.baseUrlParam = ""; - this.payload = payload; - this.headers = headers; - - this.parameters = {}; - } -} - -module.exports = Request; \ No newline at end of file diff --git a/src/Request.ts b/src/Request.ts new file mode 100644 index 0000000..0cc10f2 --- /dev/null +++ b/src/Request.ts @@ -0,0 +1,21 @@ +import { Request as IRequest } from "./types.js"; + +export default class Request implements IRequest { + baseUrl: string; + baseUrlParam: string; + payload: string | object | null; + headers: Record; + parameters: Record; + + constructor( + payload: string | object | null = null, + headers: Record = { "Content-Type": "application/json; charset=utf-8" }, + ) { + this.baseUrl = ""; + this.baseUrlParam = ""; + this.payload = payload; + this.headers = headers; + + this.parameters = {}; + } +} diff --git a/src/Response.js b/src/Response.js deleted file mode 100644 index 7cbd750..0000000 --- a/src/Response.js +++ /dev/null @@ -1,10 +0,0 @@ -class Response { - constructor (statusCode, payload, error, headers) { - this.statusCode = statusCode; - this.payload = payload; - this.error = error; - this.headers = headers; - } -} - -module.exports = Response; \ No newline at end of file diff --git a/src/Response.ts b/src/Response.ts new file mode 100644 index 0000000..b893a92 --- /dev/null +++ b/src/Response.ts @@ -0,0 +1,20 @@ +import { Response as IResponse } from "./types.js"; + +export default class Response implements IResponse { + statusCode: number; + payload: object[] | object | string | null; + error: Error | null; + headers: Record; + + constructor( + statusCode: number, + payload: object[] | object | string | null = null, + error: Error | null = null, + headers: Record = {}, + ) { + this.statusCode = statusCode; + this.payload = payload; + this.error = error; + this.headers = headers; + } +} diff --git a/src/RetrySender.ts b/src/RetrySender.ts index 8c3f689..988874b 100644 --- a/src/RetrySender.ts +++ b/src/RetrySender.ts @@ -21,7 +21,7 @@ export default class RetrySender { let response = await this.inner.send(request); for (let i = 0; i < this.maxRetries; i++) { - const statusCode = parseInt(String(response.statusCode)); + const statusCode = response.statusCode; if (!this.statusToRetry.includes(statusCode)) { break; } diff --git a/src/SigningSender.ts b/src/SigningSender.ts index ddb0701..8e9cf42 100644 --- a/src/SigningSender.ts +++ b/src/SigningSender.ts @@ -1,32 +1,26 @@ -import { Request, Response, Sender } from "./types.js"; +import { Request, Response, Sender, Signer } from "./types.js"; import SharedCredentials from "./SharedCredentials.js"; import { UnprocessableEntityError } from "./Errors.js"; -interface Signer { - sign(request: Request): void; -} - export default class SigningSender { - private signer: Signer; - private sender: Sender; + private signer: Signer; + private sender: Sender; - constructor(innerSender: Sender, signer: Signer) { - this.signer = signer; - this.sender = innerSender; - } + constructor(innerSender: Sender, signer: Signer) { + this.signer = signer; + this.sender = innerSender; + } - send(request: Request): Promise { - const sendingPostWithSharedCredentials = - request.payload && this.signer instanceof SharedCredentials; - if (sendingPostWithSharedCredentials) { - const message = - "Shared credentials cannot be used in batches with a length greater than 1 or when using the US Extract API."; - throw new UnprocessableEntityError(message); - } + send(request: Request): Promise { + const sendingPostWithSharedCredentials = + request.payload && this.signer instanceof SharedCredentials; + if (sendingPostWithSharedCredentials) { + const message = + "Shared credentials cannot be used in batches with a length greater than 1 or when using the US Extract API."; + throw new UnprocessableEntityError(message); + } - return new Promise((resolve, reject) => { - this.signer.sign(request); - this.sender.send(request).then(resolve).catch(reject); - }); - } -} \ No newline at end of file + this.signer.sign(request); + return this.sender.send(request); + } +} diff --git a/src/StatusCodeSender.js b/src/StatusCodeSender.js deleted file mode 100644 index cf40427..0000000 --- a/src/StatusCodeSender.js +++ /dev/null @@ -1,35 +0,0 @@ -const Errors = require("./Errors"); - -class StatusCodeSender { - constructor(innerSender) { - this.sender = innerSender; - } - - send(request) { - return new Promise((resolve, reject) => { - this.sender.send(request) - .then(resolve) - .catch(error => { - switch (error.statusCode) { - case 500: - error.error = new Errors.InternalServerError(); - break; - - case 503: - error.error = new Errors.ServiceUnavailableError(); - break; - - case 504: - error.error = new Errors.GatewayTimeoutError(); - break; - - default: - error.error = new Errors.DefaultError(error && error.payload && error.payload.errors[0] && error.payload.errors[0].message); - } - reject(error); - }); - }); - } -} - -module.exports = StatusCodeSender; \ No newline at end of file diff --git a/src/StatusCodeSender.ts b/src/StatusCodeSender.ts new file mode 100644 index 0000000..f32b301 --- /dev/null +++ b/src/StatusCodeSender.ts @@ -0,0 +1,46 @@ +import { + InternalServerError, + ServiceUnavailableError, + GatewayTimeoutError, + DefaultError, +} from "./Errors.js"; +import { Request, Response, Sender } from "./types.js"; + +export default class StatusCodeSender { + private sender: Sender; + + constructor(innerSender: Sender) { + this.sender = innerSender; + } + + send(request: Request): Promise { + return new Promise((resolve, reject) => { + this.sender + .send(request) + .then(resolve) + .catch((error: Response) => { + switch (error.statusCode) { + case 500: + error.error = new InternalServerError(); + break; + + case 503: + error.error = new ServiceUnavailableError(); + break; + + case 504: + error.error = new GatewayTimeoutError(); + break; + + default: { + const payload = error.payload as { + errors?: { message?: string }[]; + } | null; + error.error = new DefaultError(payload?.errors?.[0]?.message); + } + } + reject(error); + }); + }); + } +} diff --git a/src/international_address_autocomplete/Client.js b/src/international_address_autocomplete/Client.js deleted file mode 100644 index 8f25f9a..0000000 --- a/src/international_address_autocomplete/Client.js +++ /dev/null @@ -1,41 +0,0 @@ -const Errors = require("../Errors"); -const Request = require("../Request"); -const Suggestion = require("./Suggestion"); -const buildInputData = require("../util/buildInputData"); -const keyTranslationFormat = require("../util/apiToSDKKeyMap").internationalAddressAutocomplete; - -class Client { - constructor(sender) { - this.sender = sender; - } - - send(lookup) { - if (typeof lookup === "undefined") throw new Errors.UndefinedLookupError(); - - let request = new Request(); - request.parameters = buildInputData(lookup, keyTranslationFormat); - - if (lookup.addressId) { - request.baseUrlParam = lookup.addressId; - } - - return new Promise((resolve, reject) => { - this.sender.send(request) - .then(response => { - if (response.error) reject(response.error); - - lookup.result = buildSuggestionsFromResponse(response.payload); - resolve(lookup); - }) - .catch(reject); - }); - - function buildSuggestionsFromResponse(payload) { - if (payload && payload.candidates === null) return []; - - return payload.candidates.map(suggestion => new Suggestion(suggestion)); - } - } -} - -module.exports = Client; \ No newline at end of file diff --git a/src/international_address_autocomplete/Client.ts b/src/international_address_autocomplete/Client.ts new file mode 100644 index 0000000..10ede64 --- /dev/null +++ b/src/international_address_autocomplete/Client.ts @@ -0,0 +1,46 @@ +import { UndefinedLookupError } from "../Errors.js"; +import Request from "../Request.js"; +import Suggestion, { RawIntlAutocompleteSuggestion } from "./Suggestion.js"; +import buildInputData from "../util/buildInputData.js"; +import apiToSDKKeyMap from "../util/apiToSDKKeyMap.js"; +import { Sender } from "../types.js"; +import Lookup from "./Lookup.js"; + +const keyTranslationFormat = apiToSDKKeyMap.internationalAddressAutocomplete; + +export default class Client { + private sender: Sender; + + constructor(sender: Sender) { + this.sender = sender; + } + + send(lookup: Lookup): Promise { + if (typeof lookup === "undefined") throw new UndefinedLookupError(); + + const request = new Request(); + request.parameters = buildInputData(lookup, keyTranslationFormat); + + if (lookup.addressId) { + request.baseUrlParam = lookup.addressId; + } + + return new Promise((resolve, reject) => { + this.sender + .send(request) + .then((response) => { + if (response.error) return reject(response.error); + + const payload = response.payload as { + candidates: RawIntlAutocompleteSuggestion[] | null; + }; + lookup.result = + !payload || payload.candidates === null + ? [] + : payload.candidates.map((suggestion) => new Suggestion(suggestion)); + resolve(lookup); + }) + .catch(reject); + }); + } +} diff --git a/src/international_address_autocomplete/Lookup.js b/src/international_address_autocomplete/Lookup.js deleted file mode 100644 index ea4df48..0000000 --- a/src/international_address_autocomplete/Lookup.js +++ /dev/null @@ -1,19 +0,0 @@ -class Lookup { - constructor({search, addressId, country, maxResults = 5, includeOnlyLocality, includeOnlyPostalCode} = {}) { - this.result = []; - - this.search = search; - this.addressId = addressId; - this.country = country; - this.maxResults = maxResults; - this.includeOnlyLocality = includeOnlyLocality; - this.includeOnlyPostalCode = includeOnlyPostalCode; - this.customParameters = {}; - } - - addCustomParameter(key, value) { - this.customParameters[key] = value; - } -} - -module.exports = Lookup; \ No newline at end of file diff --git a/src/international_address_autocomplete/Lookup.ts b/src/international_address_autocomplete/Lookup.ts new file mode 100644 index 0000000..d157817 --- /dev/null +++ b/src/international_address_autocomplete/Lookup.ts @@ -0,0 +1,42 @@ +import Suggestion from "./Suggestion.js"; + +export default class Lookup { + result: Suggestion[]; + search: string | undefined; + addressId: string | undefined; + country: string | undefined; + maxResults: number; + includeOnlyLocality: string | undefined; + includeOnlyPostalCode: string | undefined; + customParameters: Record; + + constructor({ + search, + addressId, + country, + maxResults = 5, + includeOnlyLocality, + includeOnlyPostalCode, + }: { + search?: string; + addressId?: string; + country?: string; + maxResults?: number; + includeOnlyLocality?: string; + includeOnlyPostalCode?: string; + } = {}) { + this.result = []; + + this.search = search; + this.addressId = addressId; + this.country = country; + this.maxResults = maxResults; + this.includeOnlyLocality = includeOnlyLocality; + this.includeOnlyPostalCode = includeOnlyPostalCode; + this.customParameters = {}; + } + + addCustomParameter(key: string, value: string): void { + this.customParameters[key] = value; + } +} diff --git a/src/international_address_autocomplete/Suggestion.js b/src/international_address_autocomplete/Suggestion.js deleted file mode 100644 index c2eecda..0000000 --- a/src/international_address_autocomplete/Suggestion.js +++ /dev/null @@ -1,16 +0,0 @@ -class Suggestion { - constructor(responseData) { - this.street = responseData.street; - this.locality = responseData.locality; - this.administrativeArea = responseData.administrative_area; - this.administrativeAreaShort = responseData.administrative_area_short; - this.administrativeAreaLong = responseData.administrative_area_long; - this.postalCode = responseData.postal_code; - this.countryIso3 = responseData.country_iso3; - this.entries = responseData.entries; - this.addressText = responseData.address_text; - this.addressId = responseData.address_id; - } -} - -module.exports = Suggestion; \ No newline at end of file diff --git a/src/international_address_autocomplete/Suggestion.ts b/src/international_address_autocomplete/Suggestion.ts new file mode 100644 index 0000000..bd1e33f --- /dev/null +++ b/src/international_address_autocomplete/Suggestion.ts @@ -0,0 +1,38 @@ +export interface RawIntlAutocompleteSuggestion { + street?: string; + locality?: string; + administrative_area?: string; + administrative_area_short?: string; + administrative_area_long?: string; + postal_code?: string; + country_iso3?: string; + entries?: number; + address_text?: string; + address_id?: string; +} + +export default class Suggestion { + street: string; + locality: string; + administrativeArea: string; + administrativeAreaShort: string; + administrativeAreaLong: string; + postalCode: string; + countryIso3: string; + entries: number; + addressText: string; + addressId: string; + + constructor(responseData: RawIntlAutocompleteSuggestion) { + this.street = responseData.street ?? ""; + this.locality = responseData.locality ?? ""; + this.administrativeArea = responseData.administrative_area ?? ""; + this.administrativeAreaShort = responseData.administrative_area_short ?? ""; + this.administrativeAreaLong = responseData.administrative_area_long ?? ""; + this.postalCode = responseData.postal_code ?? ""; + this.countryIso3 = responseData.country_iso3 ?? ""; + this.entries = responseData.entries ?? 0; + this.addressText = responseData.address_text ?? ""; + this.addressId = responseData.address_id ?? ""; + } +} diff --git a/src/international_postal_code/Client.js b/src/international_postal_code/Client.js deleted file mode 100644 index 22ed7c3..0000000 --- a/src/international_postal_code/Client.js +++ /dev/null @@ -1,49 +0,0 @@ -const Request = require("../Request"); -const Result = require("./Result"); -const buildInputData = require("../util/buildInputData"); -const keyTranslationFormat = require("../util/apiToSDKKeyMap").internationalPostalCode; -const { UndefinedLookupError } = require("../Errors"); - -/** - * This client sends lookups to the Smarty International Postal Code API,
- * and attaches the results to the appropriate Lookup objects. - */ -class Client { - constructor(sender) { - this.sender = sender; - } - - /** - * Sends a single lookup for validation. - * @param data A Lookup object - * @throws SmartyException - */ - send(lookup) { - if (typeof lookup === "undefined") throw new UndefinedLookupError(); - - let request = new Request(); - request.parameters = buildInputData(lookup, keyTranslationFormat); - - return new Promise((resolve, reject) => { - this.sender - .send(request) - .then((response) => { - if (response.error) reject(response.error); - - resolve(attachLookupResults(response, lookup)); - }) - .catch(reject); - }); - - function attachLookupResults(response, lookup) { - if (response.payload && Array.isArray(response.payload)) { - lookup.result = response.payload.map((r) => new Result(r)); - } else { - lookup.result = []; - } - return lookup; - } - } -} - -module.exports = Client; diff --git a/src/international_postal_code/Client.ts b/src/international_postal_code/Client.ts new file mode 100644 index 0000000..f453c00 --- /dev/null +++ b/src/international_postal_code/Client.ts @@ -0,0 +1,44 @@ +import Request from "../Request.js"; +import Result, { RawIntlPostalCodeResult } from "./Result.js"; +import buildInputData from "../util/buildInputData.js"; +import apiToSDKKeyMap from "../util/apiToSDKKeyMap.js"; +import { UndefinedLookupError } from "../Errors.js"; +import { Sender, Response } from "../types.js"; +import Lookup from "./Lookup.js"; + +const keyTranslationFormat = apiToSDKKeyMap.internationalPostalCode; + +export default class Client { + private sender: Sender; + + constructor(sender: Sender) { + this.sender = sender; + } + + send(lookup: Lookup): Promise { + if (typeof lookup === "undefined") throw new UndefinedLookupError(); + + const request = new Request(); + request.parameters = buildInputData(lookup, keyTranslationFormat); + + return new Promise((resolve, reject) => { + this.sender + .send(request) + .then((response) => { + if (response.error) return reject(response.error); + + resolve(attachLookupResults(response, lookup)); + }) + .catch(reject); + }); + + function attachLookupResults(response: Response, lookup: Lookup): Lookup { + if (response.payload && Array.isArray(response.payload)) { + lookup.result = (response.payload as RawIntlPostalCodeResult[]).map((r) => new Result(r)); + } else { + lookup.result = []; + } + return lookup; + } + } +} diff --git a/src/international_postal_code/Lookup.js b/src/international_postal_code/Lookup.js deleted file mode 100644 index a205418..0000000 --- a/src/international_postal_code/Lookup.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * In addition to holding all of the input data for this lookup, this class also
- * will contain the result of the lookup after it comes back from the API. - * @see "https://www.smarty.com/docs/cloud/international-postal-code-api#http-request-input-fields" - */ -class Lookup { - constructor(country, postalCode, administrativeArea, locality, inputId) { - this.inputId = inputId; - this.country = country; - this.postalCode = postalCode; - this.administrativeArea = administrativeArea; - this.locality = locality; - this.result = []; - this.customParameters = {}; - } - - addCustomParameter(key, value) { - this.customParameters[key] = value; - } -} - -module.exports = Lookup; diff --git a/src/international_postal_code/Lookup.ts b/src/international_postal_code/Lookup.ts new file mode 100644 index 0000000..8bb1edb --- /dev/null +++ b/src/international_postal_code/Lookup.ts @@ -0,0 +1,31 @@ +import Result from "./Result.js"; + +export default class Lookup { + inputId: string | undefined; + country: string | undefined; + postalCode: string | undefined; + administrativeArea: string | undefined; + locality: string | undefined; + result: Result[]; + customParameters: Record; + + constructor( + country?: string, + postalCode?: string, + administrativeArea?: string, + locality?: string, + inputId?: string, + ) { + this.inputId = inputId; + this.country = country; + this.postalCode = postalCode; + this.administrativeArea = administrativeArea; + this.locality = locality; + this.result = []; + this.customParameters = {}; + } + + addCustomParameter(key: string, value: string): void { + this.customParameters[key] = value; + } +} diff --git a/src/international_postal_code/Result.js b/src/international_postal_code/Result.js deleted file mode 100644 index ccfa723..0000000 --- a/src/international_postal_code/Result.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @see "https://www.smarty.com/docs/cloud/international-postal-code-api#output-fields" - */ -class Result { - constructor(responseData) { - this.inputId = responseData.input_id; - this.administrativeArea = responseData.administrative_area; - this.superAdministrativeArea = responseData.super_administrative_area; - this.subAdministrativeArea = responseData.sub_administrative_area; - this.locality = responseData.locality; - this.dependentLocality = responseData.dependent_locality; - this.dependentLocalityName = responseData.dependent_locality_name; - this.doubleDependentLocality = responseData.double_dependent_locality; - this.postalCode = responseData.postal_code; - this.postalCodeExtra = responseData.postal_code_extra; - this.countryIso3 = responseData.country_iso_3; - } -} - -module.exports = Result; diff --git a/src/international_postal_code/Result.ts b/src/international_postal_code/Result.ts new file mode 100644 index 0000000..9f26f3b --- /dev/null +++ b/src/international_postal_code/Result.ts @@ -0,0 +1,41 @@ +export interface RawIntlPostalCodeResult { + input_id?: string; + administrative_area?: string; + super_administrative_area?: string; + sub_administrative_area?: string; + locality?: string; + dependent_locality?: string; + dependent_locality_name?: string; + double_dependent_locality?: string; + postal_code?: string; + postal_code_extra?: string; + country_iso_3?: string; +} + +export default class Result { + inputId: string; + administrativeArea: string; + superAdministrativeArea: string; + subAdministrativeArea: string; + locality: string; + dependentLocality: string; + dependentLocalityName: string; + doubleDependentLocality: string; + postalCode: string; + postalCodeExtra: string; + countryIso3: string; + + constructor(responseData: RawIntlPostalCodeResult) { + this.inputId = responseData.input_id ?? ""; + this.administrativeArea = responseData.administrative_area ?? ""; + this.superAdministrativeArea = responseData.super_administrative_area ?? ""; + this.subAdministrativeArea = responseData.sub_administrative_area ?? ""; + this.locality = responseData.locality ?? ""; + this.dependentLocality = responseData.dependent_locality ?? ""; + this.dependentLocalityName = responseData.dependent_locality_name ?? ""; + this.doubleDependentLocality = responseData.double_dependent_locality ?? ""; + this.postalCode = responseData.postal_code ?? ""; + this.postalCodeExtra = responseData.postal_code_extra ?? ""; + this.countryIso3 = responseData.country_iso_3 ?? ""; + } +} diff --git a/src/international_street/Candidate.js b/src/international_street/Candidate.js deleted file mode 100644 index 9219316..0000000 --- a/src/international_street/Candidate.js +++ /dev/null @@ -1,163 +0,0 @@ -/** - * A candidate is a possible match for an address that was submitted.
- * A lookup can have multiple candidates if the address was ambiguous. - * - * @see "https://www.smarty.com/docs/cloud/international-street-api#root" - */ -class Candidate { - constructor(responseData) { - this.organization = responseData.organization; - this.address1 = responseData.address1; - this.address2 = responseData.address2; - this.address3 = responseData.address3; - this.address4 = responseData.address4; - this.address5 = responseData.address5; - this.address6 = responseData.address6; - this.address7 = responseData.address7; - this.address8 = responseData.address8; - this.address9 = responseData.address9; - this.address10 = responseData.address10; - this.address11 = responseData.address11; - this.address12 = responseData.address12; - - this.components = {}; - if (responseData.components !== undefined) { - this.components.countryIso3 = responseData.components.country_iso_3; - this.components.superAdministrativeArea = responseData.components.super_administrative_area; - this.components.administrativeArea = responseData.components.administrative_area; - this.components.administrativeAreaIso2 = responseData.components.administrative_area_iso2; - this.components.administrativeAreaShort = responseData.components.administrative_area_short; - this.components.administrativeAreaLong = responseData.components.administrative_area_long; - this.components.subAdministrativeArea = responseData.components.sub_administrative_area; - this.components.dependentLocality = responseData.components.dependent_locality; - this.components.dependentLocalityName = responseData.components.dependent_locality_name; - this.components.doubleDependentLocality = responseData.components.double_dependent_locality; - this.components.locality = responseData.components.locality; - this.components.postalCode = responseData.components.postal_code; - this.components.postalCodeShort = responseData.components.postal_code_short; - this.components.postalCodeExtra = responseData.components.postal_code_extra; - this.components.premise = responseData.components.premise; - this.components.premiseExtra = responseData.components.premise_extra; - this.components.premisePrefixNumber = responseData.components.premise_prefix_number; - this.components.premiseNumber = responseData.components.premise_number; - this.components.premiseType = responseData.components.premise_type; - this.components.thoroughfare = responseData.components.thoroughfare; - this.components.thoroughfarePredirection = responseData.components.thoroughfare_predirection; - this.components.thoroughfarePostdirection = responseData.components.thoroughfare_postdirection; - this.components.thoroughfareName = responseData.components.thoroughfare_name; - this.components.thoroughfareTrailingType = responseData.components.thoroughfare_trailing_type; - this.components.thoroughfareType = responseData.components.thoroughfare_type; - this.components.dependentThoroughfare = responseData.components.dependent_thoroughfare; - this.components.dependentThoroughfarePredirection = responseData.components.dependent_thoroughfare_predirection; - this.components.dependentThoroughfarePostdirection = responseData.components.dependent_thoroughfare_postdirection; - this.components.dependentThoroughfareName = responseData.components.dependent_thoroughfare_name; - this.components.dependentThoroughfareTrailingType = responseData.components.dependent_thoroughfare_trailing_type; - this.components.dependentThoroughfareType = responseData.components.dependent_thoroughfare_type; - this.components.building = responseData.components.building; - this.components.buildingLeadingType = responseData.components.building_leading_type; - this.components.buildingName = responseData.components.building_name; - this.components.buildingTrailingType = responseData.components.building_trailing_type; - this.components.subBuildingType = responseData.components.sub_building_type; - this.components.subBuildingNumber = responseData.components.sub_building_number; - this.components.subBuildingName = responseData.components.sub_building_name; - this.components.subBuilding = responseData.components.sub_building; - this.components.levelType = responseData.components.level_type; - this.components.levelNumber = responseData.components.level_number; - this.components.postBox = responseData.components.post_box; - this.components.postBoxType = responseData.components.post_box_type; - this.components.postBoxNumber = responseData.components.post_box_number; - this.components.additionalContent = responseData.components.additional_content; - this.components.deliveryInstallation = responseData.components.delivery_installation; - this.components.deliveryInstallationType = responseData.components.delivery_installation_type; - this.components.deliveryInstallationQualifierName = responseData.components.delivery_installation_qualifier_name; - this.components.route = responseData.components.route; - this.components.routeNumber = responseData.components.route_number; - this.components.routeType = responseData.components.route_type; - } - - this.analysis = {}; - if (responseData.analysis !== undefined) { - this.analysis.verificationStatus = responseData.analysis.verification_status; - this.analysis.addressPrecision = responseData.analysis.address_precision; - this.analysis.maxAddressPrecision = responseData.analysis.max_address_precision; - - this.analysis.changes = {}; - if (responseData.analysis.changes !== undefined) { - this.analysis.changes.organization = responseData.analysis.changes.organization; - this.analysis.changes.address1 = responseData.analysis.changes.address1; - this.analysis.changes.address2 = responseData.analysis.changes.address2; - this.analysis.changes.address3 = responseData.analysis.changes.address3; - this.analysis.changes.address4 = responseData.analysis.changes.address4; - this.analysis.changes.address5 = responseData.analysis.changes.address5; - this.analysis.changes.address6 = responseData.analysis.changes.address6; - this.analysis.changes.address7 = responseData.analysis.changes.address7; - this.analysis.changes.address8 = responseData.analysis.changes.address8; - this.analysis.changes.address9 = responseData.analysis.changes.address9; - this.analysis.changes.address10 = responseData.analysis.changes.address10; - this.analysis.changes.address11 = responseData.analysis.changes.address11; - this.analysis.changes.address12 = responseData.analysis.changes.address12; - - this.analysis.changes.components = {}; - if (responseData.analysis.changes.components !== undefined) { - this.analysis.changes.components.countryIso3 = responseData.analysis.changes.components.country_iso_3; - this.analysis.changes.components.superAdministrativeArea = responseData.analysis.changes.components.super_administrative_area; - this.analysis.changes.components.administrativeArea = responseData.analysis.changes.components.administrative_area; - this.analysis.changes.components.administrativeAreaIso2 = responseData.analysis.changes.components.administrative_area_iso2; - this.analysis.changes.components.administrativeAreaShort = responseData.analysis.changes.components.administrative_area_short; - this.analysis.changes.components.administrativeAreaLong = responseData.analysis.changes.components.administrative_area_long; - this.analysis.changes.components.subAdministrativeArea = responseData.analysis.changes.components.sub_administrative_area; - this.analysis.changes.components.dependentLocality = responseData.analysis.changes.components.dependent_locality; - this.analysis.changes.components.dependentLocalityName = responseData.analysis.changes.components.dependent_locality_name; - this.analysis.changes.components.doubleDependentLocality = responseData.analysis.changes.components.double_dependent_locality; - this.analysis.changes.components.locality = responseData.analysis.changes.components.locality; - this.analysis.changes.components.postalCode = responseData.analysis.changes.components.postal_code; - this.analysis.changes.components.postalCodeShort = responseData.analysis.changes.components.postal_code_short; - this.analysis.changes.components.postalCodeExtra = responseData.analysis.changes.components.postal_code_extra; - this.analysis.changes.components.premise = responseData.analysis.changes.components.premise; - this.analysis.changes.components.premiseExtra = responseData.analysis.changes.components.premise_extra; - this.analysis.changes.components.premisePrefixNumber = responseData.analysis.changes.components.premise_prefix_number; - this.analysis.changes.components.premiseNumber = responseData.analysis.changes.components.premise_number; - this.analysis.changes.components.premiseType = responseData.analysis.changes.components.premise_type; - this.analysis.changes.components.thoroughfare = responseData.analysis.changes.components.thoroughfare; - this.analysis.changes.components.thoroughfarePredirection = responseData.analysis.changes.components.thoroughfare_predirection; - this.analysis.changes.components.thoroughfarePostdirection = responseData.analysis.changes.components.thoroughfare_postdirection; - this.analysis.changes.components.thoroughfareName = responseData.analysis.changes.components.thoroughfare_name; - this.analysis.changes.components.thoroughfareTrailingType = responseData.analysis.changes.components.thoroughfare_trailing_type; - this.analysis.changes.components.thoroughfareType = responseData.analysis.changes.components.thoroughfare_type; - this.analysis.changes.components.dependentThoroughfare = responseData.analysis.changes.components.dependent_thoroughfare; - this.analysis.changes.components.dependentThoroughfarePredirection = responseData.analysis.changes.components.dependent_thoroughfare_predirection; - this.analysis.changes.components.dependentThoroughfarePostdirection = responseData.analysis.changes.components.dependent_thoroughfare_postdirection; - this.analysis.changes.components.dependentThoroughfareName = responseData.analysis.changes.components.dependent_thoroughfare_name; - this.analysis.changes.components.dependentThoroughfareTrailingType = responseData.analysis.changes.components.dependent_thoroughfare_trailing_type; - this.analysis.changes.components.dependentThoroughfareType = responseData.analysis.changes.components.dependent_thoroughfare_type; - this.analysis.changes.components.building = responseData.analysis.changes.components.building; - this.analysis.changes.components.buildingLeadingType = responseData.analysis.changes.components.building_leading_type; - this.analysis.changes.components.buildingName = responseData.analysis.changes.components.building_name; - this.analysis.changes.components.buildingTrailingType = responseData.analysis.changes.components.building_trailing_type; - this.analysis.changes.components.subBuildingType = responseData.analysis.changes.components.sub_building_type; - this.analysis.changes.components.subBuildingNumber = responseData.analysis.changes.components.sub_building_number; - this.analysis.changes.components.subBuildingName = responseData.analysis.changes.components.sub_building_name; - this.analysis.changes.components.subBuilding = responseData.analysis.changes.components.sub_building; - this.analysis.changes.components.levelType = responseData.analysis.changes.components.level_type; - this.analysis.changes.components.levelNumber = responseData.analysis.changes.components.level_number; - this.analysis.changes.components.postBox = responseData.analysis.changes.components.post_box; - this.analysis.changes.components.postBoxType = responseData.analysis.changes.components.post_box_type; - this.analysis.changes.components.postBoxNumber = responseData.analysis.changes.components.post_box_number; - } - //TODO: Fill in the rest of these fields and their corresponding tests. - } - } - - this.metadata = {}; - if (responseData.metadata !== undefined) { - this.metadata.latitude = responseData.metadata.latitude; - this.metadata.longitude = responseData.metadata.longitude; - this.metadata.geocodePrecision = responseData.metadata.geocode_precision; - this.metadata.maxGeocodePrecision = responseData.metadata.max_geocode_precision; - this.metadata.addressFormat = responseData.metadata.address_format; - this.metadata.occupantUse = responseData.metadata.occupant_use; - } - } -} - -module.exports = Candidate; \ No newline at end of file diff --git a/src/international_street/Candidate.ts b/src/international_street/Candidate.ts new file mode 100644 index 0000000..3def259 --- /dev/null +++ b/src/international_street/Candidate.ts @@ -0,0 +1,463 @@ +export interface IntlStreetComponents { + countryIso3: string | undefined; + superAdministrativeArea: string | undefined; + administrativeArea: string | undefined; + administrativeAreaIso2: string | undefined; + administrativeAreaShort: string | undefined; + administrativeAreaLong: string | undefined; + subAdministrativeArea: string | undefined; + dependentLocality: string | undefined; + dependentLocalityName: string | undefined; + doubleDependentLocality: string | undefined; + locality: string | undefined; + postalCode: string | undefined; + postalCodeShort: string | undefined; + postalCodeExtra: string | undefined; + premise: string | undefined; + premiseExtra: string | undefined; + premisePrefixNumber: string | undefined; + premiseNumber: string | undefined; + premiseType: string | undefined; + thoroughfare: string | undefined; + thoroughfarePredirection: string | undefined; + thoroughfarePostdirection: string | undefined; + thoroughfareName: string | undefined; + thoroughfareTrailingType: string | undefined; + thoroughfareType: string | undefined; + dependentThoroughfare: string | undefined; + dependentThoroughfarePredirection: string | undefined; + dependentThoroughfarePostdirection: string | undefined; + dependentThoroughfareName: string | undefined; + dependentThoroughfareTrailingType: string | undefined; + dependentThoroughfareType: string | undefined; + building: string | undefined; + buildingLeadingType: string | undefined; + buildingName: string | undefined; + buildingTrailingType: string | undefined; + subBuildingType: string | undefined; + subBuildingNumber: string | undefined; + subBuildingName: string | undefined; + subBuilding: string | undefined; + levelType: string | undefined; + levelNumber: string | undefined; + postBox: string | undefined; + postBoxType: string | undefined; + postBoxNumber: string | undefined; + additionalContent: string | undefined; + deliveryInstallation: string | undefined; + deliveryInstallationType: string | undefined; + deliveryInstallationQualifierName: string | undefined; + route: string | undefined; + routeNumber: string | undefined; + routeType: string | undefined; +} + +export interface IntlChangesComponents { + countryIso3: string | undefined; + superAdministrativeArea: string | undefined; + administrativeArea: string | undefined; + administrativeAreaIso2: string | undefined; + administrativeAreaShort: string | undefined; + administrativeAreaLong: string | undefined; + subAdministrativeArea: string | undefined; + dependentLocality: string | undefined; + dependentLocalityName: string | undefined; + doubleDependentLocality: string | undefined; + locality: string | undefined; + postalCode: string | undefined; + postalCodeShort: string | undefined; + postalCodeExtra: string | undefined; + premise: string | undefined; + premiseExtra: string | undefined; + premisePrefixNumber: string | undefined; + premiseNumber: string | undefined; + premiseType: string | undefined; + thoroughfare: string | undefined; + thoroughfarePredirection: string | undefined; + thoroughfarePostdirection: string | undefined; + thoroughfareName: string | undefined; + thoroughfareTrailingType: string | undefined; + thoroughfareType: string | undefined; + dependentThoroughfare: string | undefined; + dependentThoroughfarePredirection: string | undefined; + dependentThoroughfarePostdirection: string | undefined; + dependentThoroughfareName: string | undefined; + dependentThoroughfareTrailingType: string | undefined; + dependentThoroughfareType: string | undefined; + building: string | undefined; + buildingLeadingType: string | undefined; + buildingName: string | undefined; + buildingTrailingType: string | undefined; + subBuildingType: string | undefined; + subBuildingNumber: string | undefined; + subBuildingName: string | undefined; + subBuilding: string | undefined; + levelType: string | undefined; + levelNumber: string | undefined; + postBox: string | undefined; + postBoxType: string | undefined; + postBoxNumber: string | undefined; +} + +export interface IntlChanges { + organization: string | undefined; + address1: string | undefined; + address2: string | undefined; + address3: string | undefined; + address4: string | undefined; + address5: string | undefined; + address6: string | undefined; + address7: string | undefined; + address8: string | undefined; + address9: string | undefined; + address10: string | undefined; + address11: string | undefined; + address12: string | undefined; + components: IntlChangesComponents; +} + +export interface IntlStreetAnalysis { + verificationStatus: string | undefined; + addressPrecision: string | undefined; + maxAddressPrecision: string | undefined; + changes: IntlChanges; +} + +export interface IntlStreetMetadata { + latitude: number | undefined; + longitude: number | undefined; + geocodePrecision: string | undefined; + maxGeocodePrecision: string | undefined; + addressFormat: string | undefined; + occupantUse: string | undefined; +} + +interface RawIntlStreetRawComponents { + country_iso_3?: string; + super_administrative_area?: string; + administrative_area?: string; + administrative_area_iso2?: string; + administrative_area_short?: string; + administrative_area_long?: string; + sub_administrative_area?: string; + dependent_locality?: string; + dependent_locality_name?: string; + double_dependent_locality?: string; + locality?: string; + postal_code?: string; + postal_code_short?: string; + postal_code_extra?: string; + premise?: string; + premise_extra?: string; + premise_prefix_number?: string; + premise_number?: string; + premise_type?: string; + thoroughfare?: string; + thoroughfare_predirection?: string; + thoroughfare_postdirection?: string; + thoroughfare_name?: string; + thoroughfare_trailing_type?: string; + thoroughfare_type?: string; + dependent_thoroughfare?: string; + dependent_thoroughfare_predirection?: string; + dependent_thoroughfare_postdirection?: string; + dependent_thoroughfare_name?: string; + dependent_thoroughfare_trailing_type?: string; + dependent_thoroughfare_type?: string; + building?: string; + building_leading_type?: string; + building_name?: string; + building_trailing_type?: string; + sub_building_type?: string; + sub_building_number?: string; + sub_building_name?: string; + sub_building?: string; + level_type?: string; + level_number?: string; + post_box?: string; + post_box_type?: string; + post_box_number?: string; + additional_content?: string; + delivery_installation?: string; + delivery_installation_type?: string; + delivery_installation_qualifier_name?: string; + route?: string; + route_number?: string; + route_type?: string; +} + +interface RawIntlChanges { + organization?: string; + address1?: string; + address2?: string; + address3?: string; + address4?: string; + address5?: string; + address6?: string; + address7?: string; + address8?: string; + address9?: string; + address10?: string; + address11?: string; + address12?: string; + components?: RawIntlStreetRawComponents; +} + +interface RawIntlStreetAnalysis { + verification_status?: string; + address_precision?: string; + max_address_precision?: string; + changes?: RawIntlChanges; +} + +interface RawIntlStreetMetadata { + latitude?: number; + longitude?: number; + geocode_precision?: string; + max_geocode_precision?: string; + address_format?: string; + occupant_use?: string; +} + +export interface RawIntlStreetCandidate { + organization?: string; + address1?: string; + address2?: string; + address3?: string; + address4?: string; + address5?: string; + address6?: string; + address7?: string; + address8?: string; + address9?: string; + address10?: string; + address11?: string; + address12?: string; + components?: RawIntlStreetRawComponents; + analysis?: RawIntlStreetAnalysis; + metadata?: RawIntlStreetMetadata; +} + +export default class Candidate { + organization: string; + address1: string; + address2: string; + address3: string; + address4: string; + address5: string; + address6: string; + address7: string; + address8: string; + address9: string; + address10: string; + address11: string; + address12: string; + components: IntlStreetComponents; + analysis: IntlStreetAnalysis; + metadata: IntlStreetMetadata; + + constructor(responseData: RawIntlStreetCandidate) { + this.organization = responseData.organization ?? ""; + this.address1 = responseData.address1 ?? ""; + this.address2 = responseData.address2 ?? ""; + this.address3 = responseData.address3 ?? ""; + this.address4 = responseData.address4 ?? ""; + this.address5 = responseData.address5 ?? ""; + this.address6 = responseData.address6 ?? ""; + this.address7 = responseData.address7 ?? ""; + this.address8 = responseData.address8 ?? ""; + this.address9 = responseData.address9 ?? ""; + this.address10 = responseData.address10 ?? ""; + this.address11 = responseData.address11 ?? ""; + this.address12 = responseData.address12 ?? ""; + + this.components = {} as IntlStreetComponents; + if (responseData.components !== undefined) { + this.components.countryIso3 = responseData.components.country_iso_3; + this.components.superAdministrativeArea = responseData.components.super_administrative_area; + this.components.administrativeArea = responseData.components.administrative_area; + this.components.administrativeAreaIso2 = responseData.components.administrative_area_iso2; + this.components.administrativeAreaShort = responseData.components.administrative_area_short; + this.components.administrativeAreaLong = responseData.components.administrative_area_long; + this.components.subAdministrativeArea = responseData.components.sub_administrative_area; + this.components.dependentLocality = responseData.components.dependent_locality; + this.components.dependentLocalityName = responseData.components.dependent_locality_name; + this.components.doubleDependentLocality = responseData.components.double_dependent_locality; + this.components.locality = responseData.components.locality; + this.components.postalCode = responseData.components.postal_code; + this.components.postalCodeShort = responseData.components.postal_code_short; + this.components.postalCodeExtra = responseData.components.postal_code_extra; + this.components.premise = responseData.components.premise; + this.components.premiseExtra = responseData.components.premise_extra; + this.components.premisePrefixNumber = responseData.components.premise_prefix_number; + this.components.premiseNumber = responseData.components.premise_number; + this.components.premiseType = responseData.components.premise_type; + this.components.thoroughfare = responseData.components.thoroughfare; + this.components.thoroughfarePredirection = responseData.components.thoroughfare_predirection; + this.components.thoroughfarePostdirection = + responseData.components.thoroughfare_postdirection; + this.components.thoroughfareName = responseData.components.thoroughfare_name; + this.components.thoroughfareTrailingType = responseData.components.thoroughfare_trailing_type; + this.components.thoroughfareType = responseData.components.thoroughfare_type; + this.components.dependentThoroughfare = responseData.components.dependent_thoroughfare; + this.components.dependentThoroughfarePredirection = + responseData.components.dependent_thoroughfare_predirection; + this.components.dependentThoroughfarePostdirection = + responseData.components.dependent_thoroughfare_postdirection; + this.components.dependentThoroughfareName = + responseData.components.dependent_thoroughfare_name; + this.components.dependentThoroughfareTrailingType = + responseData.components.dependent_thoroughfare_trailing_type; + this.components.dependentThoroughfareType = + responseData.components.dependent_thoroughfare_type; + this.components.building = responseData.components.building; + this.components.buildingLeadingType = responseData.components.building_leading_type; + this.components.buildingName = responseData.components.building_name; + this.components.buildingTrailingType = responseData.components.building_trailing_type; + this.components.subBuildingType = responseData.components.sub_building_type; + this.components.subBuildingNumber = responseData.components.sub_building_number; + this.components.subBuildingName = responseData.components.sub_building_name; + this.components.subBuilding = responseData.components.sub_building; + this.components.levelType = responseData.components.level_type; + this.components.levelNumber = responseData.components.level_number; + this.components.postBox = responseData.components.post_box; + this.components.postBoxType = responseData.components.post_box_type; + this.components.postBoxNumber = responseData.components.post_box_number; + this.components.additionalContent = responseData.components.additional_content; + this.components.deliveryInstallation = responseData.components.delivery_installation; + this.components.deliveryInstallationType = responseData.components.delivery_installation_type; + this.components.deliveryInstallationQualifierName = + responseData.components.delivery_installation_qualifier_name; + this.components.route = responseData.components.route; + this.components.routeNumber = responseData.components.route_number; + this.components.routeType = responseData.components.route_type; + } + + this.analysis = {} as IntlStreetAnalysis; + if (responseData.analysis !== undefined) { + this.analysis.verificationStatus = responseData.analysis.verification_status; + this.analysis.addressPrecision = responseData.analysis.address_precision; + this.analysis.maxAddressPrecision = responseData.analysis.max_address_precision; + + this.analysis.changes = {} as IntlChanges; + if (responseData.analysis.changes !== undefined) { + this.analysis.changes.organization = responseData.analysis.changes.organization; + this.analysis.changes.address1 = responseData.analysis.changes.address1; + this.analysis.changes.address2 = responseData.analysis.changes.address2; + this.analysis.changes.address3 = responseData.analysis.changes.address3; + this.analysis.changes.address4 = responseData.analysis.changes.address4; + this.analysis.changes.address5 = responseData.analysis.changes.address5; + this.analysis.changes.address6 = responseData.analysis.changes.address6; + this.analysis.changes.address7 = responseData.analysis.changes.address7; + this.analysis.changes.address8 = responseData.analysis.changes.address8; + this.analysis.changes.address9 = responseData.analysis.changes.address9; + this.analysis.changes.address10 = responseData.analysis.changes.address10; + this.analysis.changes.address11 = responseData.analysis.changes.address11; + this.analysis.changes.address12 = responseData.analysis.changes.address12; + + this.analysis.changes.components = {} as IntlChangesComponents; + if (responseData.analysis.changes.components !== undefined) { + this.analysis.changes.components.countryIso3 = + responseData.analysis.changes.components.country_iso_3; + this.analysis.changes.components.superAdministrativeArea = + responseData.analysis.changes.components.super_administrative_area; + this.analysis.changes.components.administrativeArea = + responseData.analysis.changes.components.administrative_area; + this.analysis.changes.components.administrativeAreaIso2 = + responseData.analysis.changes.components.administrative_area_iso2; + this.analysis.changes.components.administrativeAreaShort = + responseData.analysis.changes.components.administrative_area_short; + this.analysis.changes.components.administrativeAreaLong = + responseData.analysis.changes.components.administrative_area_long; + this.analysis.changes.components.subAdministrativeArea = + responseData.analysis.changes.components.sub_administrative_area; + this.analysis.changes.components.dependentLocality = + responseData.analysis.changes.components.dependent_locality; + this.analysis.changes.components.dependentLocalityName = + responseData.analysis.changes.components.dependent_locality_name; + this.analysis.changes.components.doubleDependentLocality = + responseData.analysis.changes.components.double_dependent_locality; + this.analysis.changes.components.locality = + responseData.analysis.changes.components.locality; + this.analysis.changes.components.postalCode = + responseData.analysis.changes.components.postal_code; + this.analysis.changes.components.postalCodeShort = + responseData.analysis.changes.components.postal_code_short; + this.analysis.changes.components.postalCodeExtra = + responseData.analysis.changes.components.postal_code_extra; + this.analysis.changes.components.premise = + responseData.analysis.changes.components.premise; + this.analysis.changes.components.premiseExtra = + responseData.analysis.changes.components.premise_extra; + this.analysis.changes.components.premisePrefixNumber = + responseData.analysis.changes.components.premise_prefix_number; + this.analysis.changes.components.premiseNumber = + responseData.analysis.changes.components.premise_number; + this.analysis.changes.components.premiseType = + responseData.analysis.changes.components.premise_type; + this.analysis.changes.components.thoroughfare = + responseData.analysis.changes.components.thoroughfare; + this.analysis.changes.components.thoroughfarePredirection = + responseData.analysis.changes.components.thoroughfare_predirection; + this.analysis.changes.components.thoroughfarePostdirection = + responseData.analysis.changes.components.thoroughfare_postdirection; + this.analysis.changes.components.thoroughfareName = + responseData.analysis.changes.components.thoroughfare_name; + this.analysis.changes.components.thoroughfareTrailingType = + responseData.analysis.changes.components.thoroughfare_trailing_type; + this.analysis.changes.components.thoroughfareType = + responseData.analysis.changes.components.thoroughfare_type; + this.analysis.changes.components.dependentThoroughfare = + responseData.analysis.changes.components.dependent_thoroughfare; + this.analysis.changes.components.dependentThoroughfarePredirection = + responseData.analysis.changes.components.dependent_thoroughfare_predirection; + this.analysis.changes.components.dependentThoroughfarePostdirection = + responseData.analysis.changes.components.dependent_thoroughfare_postdirection; + this.analysis.changes.components.dependentThoroughfareName = + responseData.analysis.changes.components.dependent_thoroughfare_name; + this.analysis.changes.components.dependentThoroughfareTrailingType = + responseData.analysis.changes.components.dependent_thoroughfare_trailing_type; + this.analysis.changes.components.dependentThoroughfareType = + responseData.analysis.changes.components.dependent_thoroughfare_type; + this.analysis.changes.components.building = + responseData.analysis.changes.components.building; + this.analysis.changes.components.buildingLeadingType = + responseData.analysis.changes.components.building_leading_type; + this.analysis.changes.components.buildingName = + responseData.analysis.changes.components.building_name; + this.analysis.changes.components.buildingTrailingType = + responseData.analysis.changes.components.building_trailing_type; + this.analysis.changes.components.subBuildingType = + responseData.analysis.changes.components.sub_building_type; + this.analysis.changes.components.subBuildingNumber = + responseData.analysis.changes.components.sub_building_number; + this.analysis.changes.components.subBuildingName = + responseData.analysis.changes.components.sub_building_name; + this.analysis.changes.components.subBuilding = + responseData.analysis.changes.components.sub_building; + this.analysis.changes.components.levelType = + responseData.analysis.changes.components.level_type; + this.analysis.changes.components.levelNumber = + responseData.analysis.changes.components.level_number; + this.analysis.changes.components.postBox = + responseData.analysis.changes.components.post_box; + this.analysis.changes.components.postBoxType = + responseData.analysis.changes.components.post_box_type; + this.analysis.changes.components.postBoxNumber = + responseData.analysis.changes.components.post_box_number; + } + //TODO: Fill in the rest of these fields and their corresponding tests. + } + } + + this.metadata = {} as IntlStreetMetadata; + if (responseData.metadata !== undefined) { + this.metadata.latitude = responseData.metadata.latitude; + this.metadata.longitude = responseData.metadata.longitude; + this.metadata.geocodePrecision = responseData.metadata.geocode_precision; + this.metadata.maxGeocodePrecision = responseData.metadata.max_geocode_precision; + this.metadata.addressFormat = responseData.metadata.address_format; + this.metadata.occupantUse = responseData.metadata.occupant_use; + } + } +} diff --git a/src/international_street/Client.js b/src/international_street/Client.js deleted file mode 100644 index ef0a322..0000000 --- a/src/international_street/Client.js +++ /dev/null @@ -1,42 +0,0 @@ -const Request = require("../Request"); -const Errors = require("../Errors"); -const Candidate = require("./Candidate"); -const buildInputData = require("../util/buildInputData"); -const keyTranslationFormat = require("../util/apiToSDKKeyMap").internationalStreet; - -/** - * This client sends lookups to the Smarty International Street API,
- * and attaches the results to the appropriate Lookup objects. - */ -class Client { - constructor(sender) { - this.sender = sender; - } - - send(lookup) { - if (typeof lookup === "undefined") throw new Errors.UndefinedLookupError(); - - let request = new Request(); - request.parameters = buildInputData(lookup, keyTranslationFormat); - - return new Promise((resolve, reject) => { - this.sender.send(request) - .then(response => { - if (response.error) reject(response.error); - - resolve(attachLookupCandidates(response, lookup)); - }) - .catch(reject); - }); - - function attachLookupCandidates(response, lookup) { - response.payload.map(rawCandidate => { - lookup.result.push(new Candidate(rawCandidate)); - }); - - return lookup; - } - } -} - -module.exports = Client; \ No newline at end of file diff --git a/src/international_street/Client.ts b/src/international_street/Client.ts new file mode 100644 index 0000000..a1e70ef --- /dev/null +++ b/src/international_street/Client.ts @@ -0,0 +1,45 @@ +import Request from "../Request.js"; +import { UndefinedLookupError } from "../Errors.js"; +import Candidate, { RawIntlStreetCandidate } from "./Candidate.js"; +import buildInputData from "../util/buildInputData.js"; +import apiToSDKKeyMap from "../util/apiToSDKKeyMap.js"; +import { Sender, Response } from "../types.js"; +import Lookup from "./Lookup.js"; + +const keyTranslationFormat = apiToSDKKeyMap.internationalStreet; + +export default class Client { + private sender: Sender; + + constructor(sender: Sender) { + this.sender = sender; + } + + send(lookup: Lookup): Promise { + if (typeof lookup === "undefined") throw new UndefinedLookupError(); + + const request = new Request(); + request.parameters = buildInputData(lookup, keyTranslationFormat); + + return new Promise((resolve, reject) => { + this.sender + .send(request) + .then((response) => { + if (response.error) return reject(response.error); + + resolve(attachLookupCandidates(response, lookup)); + }) + .catch(reject); + }); + + function attachLookupCandidates(response: Response, lookup: Lookup): Lookup { + if (response.payload) { + (response.payload as RawIntlStreetCandidate[]).forEach((rawCandidate) => { + lookup.result.push(new Candidate(rawCandidate)); + }); + } + + return lookup; + } + } +} diff --git a/src/international_street/Lookup.js b/src/international_street/Lookup.js deleted file mode 100644 index 4357ccb..0000000 --- a/src/international_street/Lookup.js +++ /dev/null @@ -1,90 +0,0 @@ -const UnprocessableEntityError = require("../Errors").UnprocessableEntityError; -const messages = { - countryRequired: "Country field is required.", - freeformOrAddress1Required: "Either freeform or address1 is required.", - insufficientInformation: "Insufficient information: One or more required fields were not set on the lookup.", - badGeocode: "Invalid input: geocode can only be set to 'true' (default is 'false'.", - invalidLanguage: "Invalid input: language can only be set to 'latin' or 'native'. When not set, the the output language will match the language of the input values." -}; - - -/** - * In addition to holding all of the input data for this lookup, this class also
- * will contain the result of the lookup after it comes back from the API. - *

Note: Lookups must have certain required fields set with non-blank values.
- * These can be found at the URL below.

- * @see "https://www.smarty.com/docs/cloud/international-street-api#http-input-fields" - */ -class Lookup { - constructor(country, freeform) { - this.result = []; - - this.country = country; - this.freeform = freeform; - this.address1 = undefined; - this.address2 = undefined; - this.address3 = undefined; - this.address4 = undefined; - this.organization = undefined; - this.locality = undefined; - this.administrativeArea = undefined; - this.postalCode = undefined; - this.geocode = undefined; - this.language = undefined; - this.inputId = undefined; - - this.ensureEnoughInfo = this.ensureEnoughInfo.bind(this); - this.ensureValidData = this.ensureValidData.bind(this); - this.customParameters = {}; - } - - addCustomParameter(key, value) { - this.customParameters[key] = value; - } - - ensureEnoughInfo() { - if (fieldIsMissing(this.country)) throw new UnprocessableEntityError(messages.countryRequired); - - if (fieldIsSet(this.freeform)) return true; - - if (fieldIsMissing(this.address1)) throw new UnprocessableEntityError(messages.freeformOrAddress1Required); - - if (fieldIsSet(this.postalCode)) return true; - - if (fieldIsMissing(this.locality) || fieldIsMissing(this.administrativeArea)) throw new UnprocessableEntityError(messages.insufficientInformation); - - return true; - } - - ensureValidData() { - let languageIsSetIncorrectly = () => { - let isLanguage = language => this.language.toLowerCase() === language; - - return fieldIsSet(this.language) && !(isLanguage("latin") || isLanguage("native")); - }; - - let geocodeIsSetIncorrectly = () => { - return fieldIsSet(this.geocode) && this.geocode.toLowerCase() !== "true"; - }; - - if (geocodeIsSetIncorrectly()) throw new UnprocessableEntityError(messages.badGeocode); - - if (languageIsSetIncorrectly()) throw new UnprocessableEntityError(messages.invalidLanguage); - - return true; - } -} - -function fieldIsMissing (field) { - if (!field) return true; - - const whitespaceCharacters = /\s/g; - - return field.replace(whitespaceCharacters, "").length < 1; -} - -function fieldIsSet (field) { - return !fieldIsMissing(field); -} - -module.exports = Lookup; \ No newline at end of file diff --git a/src/international_street/Lookup.ts b/src/international_street/Lookup.ts new file mode 100644 index 0000000..201e50a --- /dev/null +++ b/src/international_street/Lookup.ts @@ -0,0 +1,105 @@ +import Candidate from "./Candidate.js"; +import { UnprocessableEntityError } from "../Errors.js"; + +export type Language = "native" | "latin" | (string & {}); +export type Geocode = "true" | (string & {}); + +const messages = { + countryRequired: "Country field is required.", + freeformOrAddress1Required: "Either freeform or address1 is required.", + insufficientInformation: + "Insufficient information: One or more required fields were not set on the lookup.", + badGeocode: "Invalid input: geocode can only be set to 'true' (default is 'false'.", + invalidLanguage: + "Invalid input: language can only be set to 'latin' or 'native'. When not set, the the output language will match the language of the input values.", +}; + +function fieldIsMissing(field: string | undefined): boolean { + if (!field) return true; + + const whitespaceCharacters = /\s/g; + + return field.replace(whitespaceCharacters, "").length < 1; +} + +function fieldIsSet(field: string | undefined): boolean { + return !fieldIsMissing(field); +} + +export default class Lookup { + result: Candidate[]; + country: string | undefined; + freeform: string | undefined; + address1: string | undefined; + address2: string | undefined; + address3: string | undefined; + address4: string | undefined; + organization: string | undefined; + locality: string | undefined; + administrativeArea: string | undefined; + postalCode: string | undefined; + geocode: Geocode | undefined; + language: Language | undefined; + inputId: string | undefined; + customParameters: Record; + + constructor(country?: string, freeform?: string) { + this.result = []; + + this.country = country; + this.freeform = freeform; + this.address1 = undefined; + this.address2 = undefined; + this.address3 = undefined; + this.address4 = undefined; + this.organization = undefined; + this.locality = undefined; + this.administrativeArea = undefined; + this.postalCode = undefined; + this.geocode = undefined; + this.language = undefined; + this.inputId = undefined; + + this.ensureEnoughInfo = this.ensureEnoughInfo.bind(this); + this.ensureValidData = this.ensureValidData.bind(this); + this.customParameters = {}; + } + + addCustomParameter(key: string, value: string): void { + this.customParameters[key] = value; + } + + ensureEnoughInfo(): boolean { + if (fieldIsMissing(this.country)) throw new UnprocessableEntityError(messages.countryRequired); + + if (fieldIsSet(this.freeform)) return true; + + if (fieldIsMissing(this.address1)) + throw new UnprocessableEntityError(messages.freeformOrAddress1Required); + + if (fieldIsSet(this.postalCode)) return true; + + if (fieldIsMissing(this.locality) || fieldIsMissing(this.administrativeArea)) + throw new UnprocessableEntityError(messages.insufficientInformation); + + return true; + } + + ensureValidData(): boolean { + const languageIsSetIncorrectly = () => { + const isLanguage = (language: string) => this.language!.toLowerCase() === language; + + return fieldIsSet(this.language) && !(isLanguage("latin") || isLanguage("native")); + }; + + const geocodeIsSetIncorrectly = () => { + return fieldIsSet(this.geocode) && this.geocode!.toLowerCase() !== "true"; + }; + + if (geocodeIsSetIncorrectly()) throw new UnprocessableEntityError(messages.badGeocode); + + if (languageIsSetIncorrectly()) throw new UnprocessableEntityError(messages.invalidLanguage); + + return true; + } +} diff --git a/src/types.ts b/src/types.ts index ca372d5..a0accf0 100644 --- a/src/types.ts +++ b/src/types.ts @@ -21,8 +21,18 @@ export interface Sleeper { sleep(seconds: number): Promise; } +export interface Signer { + sign(request: Request): void; +} + +export interface BaseLookup { + inputId?: string | number | undefined; + customParameters: Record; + result: { inputIndex: number }[]; +} + export interface MockSenderInstance extends Sender { - statusCodes: string[]; + statusCodes: number[]; headers?: Record | undefined; error?: string | undefined; currentStatusCodeIndex: number; diff --git a/src/us_autocomplete_pro/Client.js b/src/us_autocomplete_pro/Client.js deleted file mode 100644 index f19703b..0000000 --- a/src/us_autocomplete_pro/Client.js +++ /dev/null @@ -1,41 +0,0 @@ -const Errors = require("../Errors"); -const Request = require("../Request"); -const Suggestion = require("./Suggestion"); -const buildInputData = require("../util/buildInputData"); -const keyTranslationFormat = require("../util/apiToSDKKeyMap").usAutocompletePro; - -/** - * This client sends lookups to the Smarty US Autocomplete Pro API,
- * and attaches the suggestions to the appropriate Lookup objects. - */ -class Client { - constructor(sender) { - this.sender = sender; - } - - send(lookup) { - if (typeof lookup === "undefined") throw new Errors.UndefinedLookupError(); - - let request = new Request(); - request.parameters = buildInputData(lookup, keyTranslationFormat); - - return new Promise((resolve, reject) => { - this.sender.send(request) - .then(response => { - if (response.error) reject(response.error); - - lookup.result = buildSuggestionsFromResponse(response.payload); - resolve(lookup); - }) - .catch(reject); - }); - - function buildSuggestionsFromResponse(payload) { - if (payload.suggestions === null) return []; - - return payload.suggestions.map(suggestion => new Suggestion(suggestion)); - } - } -} - -module.exports = Client; \ No newline at end of file diff --git a/src/us_autocomplete_pro/Client.ts b/src/us_autocomplete_pro/Client.ts new file mode 100644 index 0000000..390528c --- /dev/null +++ b/src/us_autocomplete_pro/Client.ts @@ -0,0 +1,42 @@ +import { UndefinedLookupError } from "../Errors.js"; +import Request from "../Request.js"; +import Suggestion, { RawUsAutocompleteSuggestion } from "./Suggestion.js"; +import buildInputData from "../util/buildInputData.js"; +import apiToSDKKeyMap from "../util/apiToSDKKeyMap.js"; +import { Sender } from "../types.js"; +import Lookup from "./Lookup.js"; + +const keyTranslationFormat = apiToSDKKeyMap.usAutocompletePro; + +export default class Client { + private sender: Sender; + + constructor(sender: Sender) { + this.sender = sender; + } + + send(lookup: Lookup): Promise { + if (typeof lookup === "undefined") throw new UndefinedLookupError(); + + const request = new Request(); + request.parameters = buildInputData(lookup, keyTranslationFormat); + + return new Promise((resolve, reject) => { + this.sender + .send(request) + .then((response) => { + if (response.error) return reject(response.error); + + const payload = response.payload as { + suggestions: RawUsAutocompleteSuggestion[] | null; + }; + lookup.result = + payload.suggestions === null + ? [] + : payload.suggestions.map((suggestion) => new Suggestion(suggestion)); + resolve(lookup); + }) + .catch(reject); + }); + } +} diff --git a/src/us_autocomplete_pro/Lookup.js b/src/us_autocomplete_pro/Lookup.js deleted file mode 100644 index f316c96..0000000 --- a/src/us_autocomplete_pro/Lookup.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * In addition to holding all of the input data for this lookup, this class also
- * will contain the result of the lookup after it comes back from the API. - * @see "https://www.smarty.com/docs/cloud/us-autocomplete-api#pro-http-request-input-fields" - */ -class Lookup { - /** - * @param search The beginning of an address. This is required to be set. - */ - constructor(search) { - this.result = []; - - this.search = search; - this.selected = undefined; - this.maxResults = undefined; - this.includeOnlyCities = []; - this.includeOnlyStates = []; - this.includeOnlyZIPCodes = []; - this.excludeStates = []; - this.preferCities = []; - this.preferStates = []; - this.preferZIPCodes = []; - this.preferRatio = undefined; - this.preferGeolocation = undefined; - this.source = undefined; - this.customParameters = {}; - } - - addCustomParameter(key, value) { - this.customParameters[key] = value; - } -} - -module.exports = Lookup; \ No newline at end of file diff --git a/src/us_autocomplete_pro/Lookup.ts b/src/us_autocomplete_pro/Lookup.ts new file mode 100644 index 0000000..05298fa --- /dev/null +++ b/src/us_autocomplete_pro/Lookup.ts @@ -0,0 +1,44 @@ +import Suggestion from "./Suggestion.js"; + +export type Geolocation = "city" | "none" | (string & {}); + +export default class Lookup { + result: Suggestion[]; + search: string | undefined; + selected: string | undefined; + maxResults: number | undefined; + includeOnlyCities: string[]; + includeOnlyStates: string[]; + includeOnlyZIPCodes: string[]; + excludeStates: string[]; + preferCities: string[]; + preferStates: string[]; + preferZIPCodes: string[]; + preferRatio: number | undefined; + preferGeolocation: Geolocation | undefined; + source: string | undefined; + customParameters: Record; + + constructor(search?: string) { + this.result = []; + + this.search = search; + this.selected = undefined; + this.maxResults = undefined; + this.includeOnlyCities = []; + this.includeOnlyStates = []; + this.includeOnlyZIPCodes = []; + this.excludeStates = []; + this.preferCities = []; + this.preferStates = []; + this.preferZIPCodes = []; + this.preferRatio = undefined; + this.preferGeolocation = undefined; + this.source = undefined; + this.customParameters = {}; + } + + addCustomParameter(key: string, value: string): void { + this.customParameters[key] = value; + } +} diff --git a/src/us_autocomplete_pro/Suggestion.js b/src/us_autocomplete_pro/Suggestion.js deleted file mode 100644 index e75e0ab..0000000 --- a/src/us_autocomplete_pro/Suggestion.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @see "https://www.smarty.com/docs/cloud/us-autocomplete-api#pro-http-response" - */ -class Suggestion { - constructor(responseData) { - this.streetLine = responseData.street_line; - this.secondary = responseData.secondary; - this.city = responseData.city; - this.state = responseData.state; - this.zipcode = responseData.zipcode; - this.entries = responseData.entries; - - if (responseData.source) { - this.source = responseData.source; - } - } -} - -module.exports = Suggestion; \ No newline at end of file diff --git a/src/us_autocomplete_pro/Suggestion.ts b/src/us_autocomplete_pro/Suggestion.ts new file mode 100644 index 0000000..3daf4d8 --- /dev/null +++ b/src/us_autocomplete_pro/Suggestion.ts @@ -0,0 +1,32 @@ +export interface RawUsAutocompleteSuggestion { + street_line?: string; + secondary?: string; + city?: string; + state?: string; + zipcode?: string; + entries?: number; + source?: string; +} + +export default class Suggestion { + streetLine: string; + secondary: string; + city: string; + state: string; + zipcode: string; + entries: number; + source: string | undefined; + + constructor(responseData: RawUsAutocompleteSuggestion) { + this.streetLine = responseData.street_line ?? ""; + this.secondary = responseData.secondary ?? ""; + this.city = responseData.city ?? ""; + this.state = responseData.state ?? ""; + this.zipcode = responseData.zipcode ?? ""; + this.entries = responseData.entries ?? 0; + + if (responseData.source) { + this.source = responseData.source; + } + } +} diff --git a/src/us_enrichment/Client.js b/src/us_enrichment/Client.js deleted file mode 100644 index dc90252..0000000 --- a/src/us_enrichment/Client.js +++ /dev/null @@ -1,112 +0,0 @@ -const Errors = require("../Errors"); -const Request = require("../Request"); -const buildInputData = require("../util/buildInputData"); -const {usEnrichment: keyTranslationFormat} = require("../util/apiToSDKKeyMap"); - -class Client { - constructor(sender) { - this.sender = sender; - } - - sendPrincipal(lookup) { - if (typeof lookup === "undefined") throw new Errors.UndefinedLookupError(); - - let request = new Request(); - request.parameters = buildInputData(lookup, keyTranslationFormat); - - request.baseUrlParam = lookup.smartyKey + "/property/principal"; - - return new Promise((resolve, reject) => { - this.sender.send(request) - .then(response => { - if (response.error) reject(response.error); - - lookup.response = response.payload; - resolve(lookup); - }) - .catch(reject); - }); - } - - sendFinancial(lookup) { - if (typeof lookup === "undefined") throw new Errors.UndefinedLookupError(); - - let request = new Request(); - request.parameters = buildInputData(lookup, keyTranslationFormat); - - request.baseUrlParam = lookup.smartyKey + "/property/financial"; - - return new Promise((resolve, reject) => { - this.sender.send(request) - .then(response => { - if (response.error) reject(response.error); - - lookup.response = response.payload; - resolve(lookup); - }) - .catch(reject); - }); - } - - sendGeo(lookup) { - if (typeof lookup === "undefined") throw new Errors.UndefinedLookupError(); - - let request = new Request(); - request.parameters = buildInputData(lookup, keyTranslationFormat); - - request.baseUrlParam = lookup.smartyKey + "/geo-reference"; - - return new Promise((resolve, reject) => { - this.sender.send(request) - .then(response => { - if (response.error) reject(response.error); - - lookup.response = response.payload; - resolve(lookup); - }) - .catch(reject); - }); - } - - sendSecondary(lookup) { - if (typeof lookup === "undefined") throw new Errors.UndefinedLookupError(); - - let request = new Request(); - request.parameters = buildInputData(lookup, keyTranslationFormat); - - request.baseUrlParam = lookup.smartyKey + "/secondary"; - - return new Promise((resolve, reject) => { - this.sender.send(request) - .then(response => { - if (response.error) reject(response.error); - - lookup.response = response.payload; - resolve(lookup); - }) - .catch(reject); - }); - } - - sendSecondaryCount(lookup) { - if (typeof lookup === "undefined") throw new Errors.UndefinedLookupError(); - - let request = new Request(); - request.parameters = buildInputData(lookup, keyTranslationFormat); - - request.baseUrlParam = lookup.smartyKey + "/secondary/count"; - - return new Promise((resolve, reject) => { - this.sender.send(request) - .then(response => { - if (response.error) reject(response.error); - - lookup.response = response.payload; - resolve(lookup); - }) - .catch(reject); - }); - } -} - -module.exports = Client; \ No newline at end of file diff --git a/src/us_enrichment/Client.ts b/src/us_enrichment/Client.ts new file mode 100644 index 0000000..bccea75 --- /dev/null +++ b/src/us_enrichment/Client.ts @@ -0,0 +1,122 @@ +import { UndefinedLookupError } from "../Errors.js"; +import Request from "../Request.js"; +import buildInputData from "../util/buildInputData.js"; +import apiToSDKKeyMap from "../util/apiToSDKKeyMap.js"; +import { Sender } from "../types.js"; +import Lookup from "./Lookup.js"; +import { Response, FinancialResponse, GeoResponse } from "./Response.js"; + +const keyTranslationFormat = apiToSDKKeyMap.usEnrichment; + +export default class Client { + private sender: Sender; + + constructor(sender: Sender) { + this.sender = sender; + } + + sendPrincipal(lookup: Lookup): Promise { + if (typeof lookup === "undefined") throw new UndefinedLookupError(); + + const request = new Request(); + request.parameters = buildInputData(lookup, keyTranslationFormat); + + request.baseUrlParam = lookup.smartyKey + "/property/principal"; + + return new Promise((resolve, reject) => { + this.sender + .send(request) + .then((response) => { + if (response.error) return reject(response.error); + + lookup.response = new Response(response.payload as Record); + resolve(lookup); + }) + .catch(reject); + }); + } + + sendFinancial(lookup: Lookup): Promise { + if (typeof lookup === "undefined") throw new UndefinedLookupError(); + + const request = new Request(); + request.parameters = buildInputData(lookup, keyTranslationFormat); + + request.baseUrlParam = lookup.smartyKey + "/property/financial"; + + return new Promise((resolve, reject) => { + this.sender + .send(request) + .then((response) => { + if (response.error) return reject(response.error); + + lookup.response = new FinancialResponse(response.payload as Record); + resolve(lookup); + }) + .catch(reject); + }); + } + + sendGeo(lookup: Lookup): Promise { + if (typeof lookup === "undefined") throw new UndefinedLookupError(); + + const request = new Request(); + request.parameters = buildInputData(lookup, keyTranslationFormat); + + request.baseUrlParam = lookup.smartyKey + "/geo-reference"; + + return new Promise((resolve, reject) => { + this.sender + .send(request) + .then((response) => { + if (response.error) return reject(response.error); + + lookup.response = new GeoResponse(response.payload as Record); + resolve(lookup); + }) + .catch(reject); + }); + } + + sendSecondary(lookup: Lookup): Promise { + if (typeof lookup === "undefined") throw new UndefinedLookupError(); + + const request = new Request(); + request.parameters = buildInputData(lookup, keyTranslationFormat); + + request.baseUrlParam = lookup.smartyKey + "/secondary"; + + return new Promise((resolve, reject) => { + this.sender + .send(request) + .then((response) => { + if (response.error) return reject(response.error); + + lookup.response = new Response(response.payload as Record); + resolve(lookup); + }) + .catch(reject); + }); + } + + sendSecondaryCount(lookup: Lookup): Promise { + if (typeof lookup === "undefined") throw new UndefinedLookupError(); + + const request = new Request(); + request.parameters = buildInputData(lookup, keyTranslationFormat); + + request.baseUrlParam = lookup.smartyKey + "/secondary/count"; + + return new Promise((resolve, reject) => { + this.sender + .send(request) + .then((response) => { + if (response.error) return reject(response.error); + + lookup.response = new Response(response.payload as Record); + resolve(lookup); + }) + .catch(reject); + }); + } +} diff --git a/src/us_enrichment/Lookup.js b/src/us_enrichment/Lookup.js deleted file mode 100644 index 045947c..0000000 --- a/src/us_enrichment/Lookup.js +++ /dev/null @@ -1,19 +0,0 @@ -class Lookup { - constructor(smartyKey, include, exclude, dataset, dataSubset) { - this.smartyKey = smartyKey; - this.include = include; - this.exclude = exclude; - this.dataset = dataset; - this.dataSubset = dataSubset; - this.features = undefined; - - this.response = {}; - this.customParameters = {}; - }; - - addCustomParameter(key, value) { - this.customParameters[key] = value; - } -} - -module.exports = Lookup; \ No newline at end of file diff --git a/src/us_enrichment/Lookup.ts b/src/us_enrichment/Lookup.ts new file mode 100644 index 0000000..dfeb49c --- /dev/null +++ b/src/us_enrichment/Lookup.ts @@ -0,0 +1,34 @@ +import { Response, FinancialResponse, GeoResponse } from "./Response.js"; + +export default class Lookup { + smartyKey: string | undefined; + include: string | undefined; + exclude: string | undefined; + dataset: string | undefined; + dataSubset: string | undefined; + features: string | undefined; + response: Response | FinancialResponse | GeoResponse; + customParameters: Record; + + constructor( + smartyKey?: string, + include?: string, + exclude?: string, + dataset?: string, + dataSubset?: string, + ) { + this.smartyKey = smartyKey; + this.include = include; + this.exclude = exclude; + this.dataset = dataset; + this.dataSubset = dataSubset; + this.features = undefined; + + this.response = new Response({}); + this.customParameters = {}; + } + + addCustomParameter(key: string, value: string): void { + this.customParameters[key] = value; + } +} diff --git a/src/us_enrichment/Response.js b/src/us_enrichment/Response.js deleted file mode 100644 index 26cb040..0000000 --- a/src/us_enrichment/Response.js +++ /dev/null @@ -1,607 +0,0 @@ -class Response { - constructor(responseData) { - this.smartyKey = responseData.smarty_key; - this.dataSetName = responseData.data_set_name; - this.dataSubsetName = responseData.data_subset_name; - - this.attributes = {}; - if (responseData.attributes) { - this.attributes.firstFloorSqft = responseData.attributes["1st_floor_sqft"]; - this.attributes.secondFlootSqft = responseData.attributes["2nd_floor_sqft"]; - this.attributes.acres = responseData.attributes.acres; - this.attributes.addressInfoPrivacy = responseData.attributes.address_info_privacy; - this.attributes.airConditioner = responseData.attributes.air_conditioner; - this.attributes.arborPergola = responseData.attributes.arbor_pergola; - this.attributes.assessedImprovementPercent = responseData.attributes.assessed_improvement_percent; - this.attributes.assessedImprovementValue = responseData.attributes.assessed_improvement_value; - this.attributes.assessedLandValue = responseData.attributes.assessed_land_value; - this.attributes.assessedValue = responseData.attributes.assessed_value; - this.attributes.assessorLastUpdate = responseData.attributes.assessor_last_update; - this.attributes.assessorTaxrollUpdate = responseData.attributes.assessor_taxroll_update; - this.attributes.atticArea = responseData.attributes.attic_area; - this.attributes.atticFlag = responseData.attributes.attic_flag; - this.attributes.balcony = responseData.attributes.balcony; - this.attributes.balconyArea = responseData.attributes.balcony_area; - this.attributes.basementSqft = responseData.attributes.basement_sqft; - this.attributes.basementSqftFinished = responseData.attributes.basement_sqft_finished; - this.attributes.basementsqftUnfinished = responseData.attributes.basement_sqft_unfinished; - this.attributes.bathHouse = responseData.attributes.bath_house; - this.attributes.bathHouseSqft = responseData.attributes.bath_house_sqft; - this.attributes.bathroomsPartial = responseData.attributes.bathrooms_partial; - this.attributes.bathroomsTotal = responseData.attributes.bathrooms_total; - this.attributes.bedrooms = responseData.attributes.bedrooms; - this.attributes.block1 = responseData.attributes.block_1; - this.attributes.block2 = responseData.attributes.block_2; - this.attributes.boatAccess = responseData.attributes.boat_access; - this.attributes.boatHouse = responseData.attributes.boat_house; - this.attributes.boatHouseSqft = responseData.attributes.boat_house_sqft; - this.attributes.boatLift = responseData.attributes.boat_lift; - this.attributes.bonusRoom = responseData.attributes.bonus_room; - this.attributes.breakfastNook = responseData.attributes.breakfast_nook; - this.attributes.breezeway = responseData.attributes.breezeway; - this.attributes.buildingDefinitionCode = responseData.attributes.building_definition; - this.attributes.buildingSqft = responseData.attributes.building_sqft; - this.attributes.cabin = responseData.attributes.cabin; - this.attributes.cabinSqft = responseData.attributes.cabin_sqft; - this.attributes.canopy = responseData.attributes.canopy; - this.attributes.canopySqft = responseData.attributes.canopy_sqft; - this.attributes.carport = responseData.attributes.carport; - this.attributes.carportSqft = responseData.attributes.carport_sqft; - this.attributes.cbsaCode = responseData.attributes.cbsa_code; - this.attributes.cbsaName = responseData.attributes.cbsa_name; - this.attributes.cellar = responseData.attributes.cellar; - this.attributes.censusBlock = responseData.attributes.census_block; - this.attributes.censusTract = responseData.attributes.census_tract; - this.attributes.censusBlockGroup = responseData.attributes.census_block_group; - this.attributes.censusFipsPlaceCode = responseData.attributes.census_fips_place_code; - this.attributes.censusTract = responseData.attributes.census_tract; - this.attributes.centralVacuum = responseData.attributes.central_vacuum; - this.attributes.codeTitleCompany = responseData.attributes.code_title_company; - this.attributes.combinedStatisticalArea = responseData.attributes.combined_statistical_area; - this.attributes.communityRec = responseData.attributes.community_rec; - this.attributes.companyFlag = responseData.attributes.company_flag; - this.attributes.congressionalDistrict = responseData.attributes.congressional_district; - this.attributes.constructionType = responseData.attributes.construction_type; - this.attributes.contactCity = responseData.attributes.contact_city; - this.attributes.contactCrrt = responseData.attributes.contact_crrt; - this.attributes.contactFullAddress = responseData.attributes.contact_full_address; - this.attributes.contactHouseNumber = responseData.attributes.contact_house_number; - this.attributes.contactMailInfoFormat = responseData.attributes.contact_main_info_format; - this.attributes.contactMailInfoPrivacy = responseData.attributes.contact_mail_info_privacy; - this.attributes.contactMailingCounty = responseData.attributes.contact_mailing_county; - this.attributes.contactMailingFips = responseData.attributes.contact_mailing_fips; - this.attributes.contactPostDirection = responseData.attributes.contact_post_direction; - this.attributes.contactPreDirection = responseData.attributes.contact_pre_direction; - this.attributes.contactState = responseData.attributes.contact_state; - this.attributes.contactStreetName = responseData.attributes.contact_street_name; - this.attributes.contactSuffix = responseData.attributes.contact_suffix; - this.attributes.contactUnitDesignator = responseData.attributes.contact_unit_designator; - this.attributes.contactValue = responseData.attributes.contact_value; - this.attributes.contactZip = responseData.attributes.contact_zip; - this.attributes.contactZip4 = responseData.attributes.contact_zip4; - this.attributes.courtyard = responseData.attributes.courtyard; - this.attributes.courtyardArea = responseData.attributes.courtyard_area; - this.attributes.deck = responseData.attributes.deck; - this.attributes.deckArea = responseData.attributes.deck_area; - this.attributes.deedDocumentPage = responseData.attributes.deed_document_page; - this.attributes.deedDocumentBook = responseData.attributes.deed_document_book; - this.attributes.deedDocumentNumber = responseData.attributes.deed_document_number; - this.attributes.deedOwnerFirstName = responseData.attributes.deed_owner_first_name; - this.attributes.deedOwnerFirstName2 = responseData.attributes.deed_owner_first_name2; - this.attributes.deedOwnerFirstName3 = responseData.attributes.deed_owner_first_name3; - this.attributes.deedOwnerFirstName4 = responseData.attributes.deed_owner_first_name4; - this.attributes.deedOwnerFullName = responseData.attributes.deed_owner_full_name; - this.attributes.deedOwnerFullName2 = responseData.attributes.deed_owner_full_name2; - this.attributes.deedOwnerFullName3 = responseData.attributes.deed_owner_full_name3; - this.attributes.deedOwnerFullName4 = responseData.attributes.deed_owner_full_name4; - this.attributes.deedOwnerLastName = responseData.attributes.deed_owner_last_name; - this.attributes.deedOwnerLastName2 = responseData.attributes.deed_owner_last_name2; - this.attributes.deedOwnerLastName3 = responseData.attributes.deed_owner_last_name3; - this.attributes.deedOwnerLastName4 = responseData.attributes.deed_owner_last_name4; - this.attributes.deedOwnerMiddleName = responseData.attributes.deed_owner_middle_name; - this.attributes.deedOwnerMiddleName2 = responseData.attributes.deed_owner_middle_name2; - this.attributes.deedOwnerMiddleName3 = responseData.attributes.deed_owner_middle_name3; - this.attributes.deedOwnerMiddleName4 = responseData.attributes.deed_owner_middle_name4; - this.attributes.deedOwnerSuffix = responseData.attributes.deed_owner_suffix; - this.attributes.deedOwnerSuffix2 = responseData.attributes.deed_owner_suffix2; - this.attributes.deedOwnerSuffix3 = responseData.attributes.deed_owner_suffix3; - this.attributes.deedOwnerSuffix4 = responseData.attributes.deed_owner_suffix4; - this.attributes.deedSaleDate = responseData.attributes.deed_sale_date; - this.attributes.deedSalePrice = responseData.attributes.deed_sale_price; - this.attributes.deedTransactionId = responseData.attributes.deed_transaction_id; - this.attributes.depthLinearFootage = responseData.attributes.depth_linear_footage; - this.attributes.disabledTaxExemption = responseData.attributes.disabled_tax_exemption; - this.attributes.drivewaySqft = responseData.attributes.driveway_sqft; - this.attributes.drivewayType = responseData.attributes.driveway_type; - this.attributes.effectiveYearBuilt = responseData.attributes.effective_year_built; - this.attributes.elevationFeet = responseData.attributes.elevation_feet; - this.attributes.elevator = responseData.attributes.elevator; - this.attributes.equestrianArena = responseData.attributes.equestrian_arena; - this.attributes.escalator = responseData.attributes.escalator; - this.attributes.exerciseRoom = responseData.attributes.exercise_room; - this.attributes.exteriorWalls = responseData.attributes.exterior_walls; - this.attributes.familyRoom = responseData.attributes.family_room; - this.attributes.financialHistory = !responseData.attributes.financial_history ? [] : responseData.attributes.financial_history.map(history => { - return { - codeTitleCompany: history.code_title_company, - instrumentDate: history.instrument_date, - interestRateType2: history.interest_rate_type_2, - lenderAddress: history.lender_address, - lenderAddress2: history.lender_address_2, - lenderCity: history.lender_city, - lenderCity2: history.lender_city_2, - lenderCode: history.lender_code, - lenderCode2: history.lender_code_2, - lenderFirstName: history.lender_first_name, - lenderFirstName2: history.lender_first_name_2, - lenderLastName: history.lender_last_name, - lenderLastName2: history.lender_last_name_2, - lenderName: history.lender_name, - lenderName2: history.lender_name_2, - lenderSellerCarryBack: history.lender_seller_carry_back, - lenderSellerCarryBack2: history.lender_seller_carry_back_2, - lenderState: history.lender_state, - lenderState2: history.lender_state_2, - lenderZip: history.lender_zip, - lenderZip2: history.lender_zip_2, - lenderZipExtended: history.lender_zip_extended, - lenderZipExtended2: history.lender_zip_extended_2, - mortgageAmount: history.mortgage_amount, - mortgageAmount2: history.mortgage_amount_2, - mortgageDueDate: history.mortgage_due_date, - mortgageDueDate2: history.mortgage_due_date_2, - mortgageInterestRate: history.mortgage_interest_rate, - mortgageInterestRateType: history.mortgage_interest_rate_type, - mortgageLenderCode: history.mortgage_lender_code, - mortgageRate: history.mortgage_rate, - mortgageRate2: history.mortgage_rate_2, - mortgageRecordingDate: history.mortgage_recording_date, - mortgageRecordingDate2: history.mortgage_recording_date_2, - mortgageTerm: history.mortgage_term, - mortgageTerm2: history.mortgage_term_2, - mortgageTermType: history.mortgage_term_type, - mortgageTermType2: history.mortgage_term_type_2, - mortgageType: history.mortgage_type, - mortgageType2: history.mortgage_type_2, - multiParcelFlag: history.multi_parcel_flag, - nameTitleCompany: history.name_title_company, - recordingDate: history.recording_date, - transferAmount: history.transfer_amount, - } - }) - this.attributes.fence = responseData.attributes.fence; - this.attributes.fenceArea = responseData.attributes.fence_area; - this.attributes.fipsCode = responseData.attributes.fips_code; - this.attributes.fireResistanceCode = responseData.attributes.fire_resistance_code; - this.attributes.fireSprinklersFlag = responseData.attributes.fire_sprinkler_flag; - this.attributes.fireplace = responseData.attributes.fireplace; - this.attributes.fireplaceNumber = responseData.attributes.fireplace_number; - this.attributes.firstName = responseData.attributes.first_name; - this.attributes.firstName2 = responseData.attributes.first_name2; - this.attributes.firstName3 = responseData.attributes.first_name3; - this.attributes.firstName4 = responseData.attributes.first_name4; - this.attributes.flooring = responseData.attributes.flooring; - this.attributes.foundation = responseData.attributes.foundation; - this.attributes.gameRoom = responseData.attributes.game_room; - this.attributes.garage = responseData.attributes.garage; - this.attributes.garageSqft = responseData.attributes.garage_sqft; - this.attributes.gazebo = responseData.attributes.gazebo; - this.attributes.gazeboSqft = responseData.attributes.gazebo_sqft; - this.attributes.golfCourse = responseData.attributes.golf_course; - this.attributes.grainery = responseData.attributes.grainery; - this.attributes.grainerySqft = responseData.attributes.grainery_sqft; - this.attributes.greatRoom = responseData.attributes.great_room; - this.attributes.greenhouse = responseData.attributes.greenhouse; - this.attributes.greenhouseSqft = responseData.attributes.greenhouse_sqft; - this.attributes.grossSqft = responseData.attributes.gross_sqft; - this.attributes.guesthouse = responseData.attributes.guesthouse; - this.attributes.guesthouseSqft = responseData.attributes.guesthouse_sqft; - this.attributes.handicapAccessibility = responseData.attributes.handicap_accessibility; - this.attributes.heat = responseData.attributes.heat; - this.attributes.heatFuelType = responseData.attributes.heat_fuel_type; - this.attributes.hobbyRoom = responseData.attributes.hobby_room; - this.attributes.homeownerTaxExemption = responseData.attributes.homeowner_tax_exemption; - this.attributes.instrumentDate = responseData.attributes.instrument_date; - this.attributes.intercomSystem = responseData.attributes.intercom_system; - this.attributes.interestRateType2 = responseData.attributes.interest_rate_type_2; - this.attributes.interiorStructure = responseData.attributes.interior_structure; - this.attributes.kennel = responseData.attributes.kennel; - this.attributes.kennelSqft = responseData.attributes.kennel_sqft; - this.attributes.landUseCode = responseData.attributes.land_use_code; - this.attributes.landUseGroup = responseData.attributes.land_use_group; - this.attributes.landUseStandard = responseData.attributes.land_use_standard; - this.attributes.lastName = responseData.attributes.last_name; - this.attributes.lastName2 = responseData.attributes.last_name_2; - this.attributes.lastName3 = responseData.attributes.last_name_3; - this.attributes.lastName4 = responseData.attributes.last_name_4; - this.attributes.latitude = responseData.attributes.latitude; - this.attributes.laundry = responseData.attributes.laundry; - this.attributes.leanTo = responseData.attributes.lean_to; - this.attributes.leanToSqft = responseData.attributes.lean_to_sqft; - this.attributes.legalDescription = responseData.attributes.legal_description; - this.attributes.legalUnit = responseData.attributes.legal_unit; - this.attributes.lenderAddress = responseData.attributes.lender_address; - this.attributes.lenderAddress2 = responseData.attributes.lender_address_2; - this.attributes.lenderCity = responseData.attributes.lender_city; - this.attributes.lenderCity2 = responseData.attributes.lender_city_2; - this.attributes.lenderCode = responseData.attributes.lender_code; - this.attributes.lenderCode2 = responseData.attributes.lender_code_2; - this.attributes.lenderFirstName = responseData.attributes.lender_first_name; - this.attributes.lenderFirstName2 = responseData.attributes.lender_first_name_2; - this.attributes.lenderLastName = responseData.attributes.lender_last_name; - this.attributes.lenderLastName2 = responseData.attributes.lender_last_name_2; - this.attributes.lenderName = responseData.attributes.lender_name; - this.attributes.lenderName2 = responseData.attributes.lender_name_2; - this.attributes.lenderSellerCarryBack = responseData.attributes.lender_seller_carry_back; - this.attributes.lenderSellerCarryBack2 = responseData.attributes.lender_seller_carry_back_2; - this.attributes.lenderState = responseData.attributes.lender_state; - this.attributes.lenderState2 = responseData.attributes.lender_state_2; - this.attributes.lenderZip = responseData.attributes.lender_zip; - this.attributes.lenderZip2 = responseData.attributes.lender_zip_2; - this.attributes.lenderZipExtended = responseData.attributes.lender_zip_extended; - this.attributes.lenderZipExtended2 = responseData.attributes.lender_zip_extended_2; - this.attributes.loadingPlatform = responseData.attributes.loading_platform; - this.attributes.loadingPlatformSqft = responseData.attributes.loading_platform_sqft; - this.attributes.longitude = responseData.attributes.longitude; - this.attributes.lot1 = responseData.attributes.lot_1; - this.attributes.lot2 = responseData.attributes.lot_2; - this.attributes.lot3 = responseData.attributes.lot_3; - this.attributes.lotSqft = responseData.attributes.lot_sqft; - this.attributes.marketImprovementPercent = responseData.attributes.market_improvement_percent; - this.attributes.marketImprovementValue = responseData.attributes.market_improvement_value; - this.attributes.marketLandValue = responseData.attributes.market_land_value; - this.attributes.marketValueYear = responseData.attributes.market_value_year; - this.attributes.matchType = responseData.attributes.match_type; - this.attributes.mediaRoom = responseData.attributes.media_room; - this.attributes.metroDivision = responseData.attributes.metro_division; - this.attributes.middleName = responseData.attributes.middle_name; - this.attributes.middleName2 = responseData.attributes.middle_name_2; - this.attributes.middleName3 = responseData.attributes.middle_name_3; - this.attributes.middleName4 = responseData.attributes.middle_name_4; - this.attributes.milkhouse = responseData.attributes.milkhouse; - this.attributes.milkhouseSqft = responseData.attributes.milkhouse_sqft; - this.attributes.minorCivilDivisionCode = responseData.attributes.minor_civil_division_code; - this.attributes.minorCivilDivisionName = responseData.attributes.minor_civil_division_name; - this.attributes.mobileHomeHookup = responseData.attributes.mobile_home_hookup; - this.attributes.mortgageAmount = responseData.attributes.mortgage_amount; - this.attributes.mortgageAmount2 = responseData.attributes.mortgage_amount_2; - this.attributes.mortgageDueDate = responseData.attributes.mortgage_due_date; - this.attributes.mortgageDueDate2 = responseData.attributes.mortgage_due_date_2; - this.attributes.mortgageInterestRate = responseData.attributes.mortgage_interest_rate; - this.attributes.mortgageInterestRateType = responseData.attributes.mortgage_interest_rate_type; - this.attributes.mortgageLenderCode = responseData.attributes.mortgage_lender_code; - this.attributes.mortgageRate2 = responseData.attributes.mortgage_rate_2; - this.attributes.mortgageRecordingDate = responseData.attributes.mortgage_recording_date; - this.attributes.mortgageRecordingDate2 = responseData.attributes.mortgage_recording_date_2; - this.attributes.mortgageTerm = responseData.attributes.mortgage_term; - this.attributes.mortgageTerm2 = responseData.attributes.mortgage_term_2; - this.attributes.mortgageTermType = responseData.attributes.mortgage_term_type; - this.attributes.mortgageTermType2 = responseData.attributes.mortgage_term_type_2; - this.attributes.mortgageType = responseData.attributes.mortgage_type; - this.attributes.mortgageType2 = responseData.attributes.mortgage_type_2; - this.attributes.msaCode = responseData.attributes.msa_code; - this.attributes.msaName = responseData.attributes.msa_name; - this.attributes.mudRoom = responseData.attributes.mud_room; - this.attributes.multiParcelFlag = responseData.attributes.multi_parcel_flag; - this.attributes.nameTitleCompany = responseData.attributes.name_title_company; - this.attributes.neighborhoodCode = responseData.attributes.neighborhood_code; - this.attributes.numberOfBuildings = responseData.attributes.number_of_buildings; - this.attributes.office = responseData.attributes.office; - this.attributes.officeSqft = responseData.attributes.office_sqft; - this.attributes.otherTaxExemption = responseData.attributes.other_tax_exemption; - this.attributes.outdoorKitchenFireplace = responseData.attributes.outdoor_kitchen_fireplace; - this.attributes.overheadDoor = responseData.attributes.overhead_door; - this.attributes.ownerFullName = responseData.attributes.owner_full_name; - this.attributes.ownerFullName2 = responseData.attributes.owner_full_name_2; - this.attributes.ownerFullName3 = responseData.attributes.owner_full_name_3; - this.attributes.ownerFullName4 = responseData.attributes.owner_full_name_4; - this.attributes.ownerOccupancyStatus = responseData.attributes.owner_occupancy_status; - this.attributes.ownershipTransferDate = responseData.attributes.ownership_transfer_date; - this.attributes.ownershipTransferDocNumber = responseData.attributes.ownership_transfer_doc_number; - this.attributes.ownershipTransferTransactionId = responseData.attributes.ownership_transfer_transaction_id; - this.attributes.ownershipType = responseData.attributes.ownership_type; - this.attributes.ownershipType2 = responseData.attributes.ownership_type_2; - this.attributes.ownershipVestingRelationCode = responseData.attributes.ownership_vesting_relation_code; - this.attributes.parcelAccountNumber = responseData.attributes.parcel_account_number; - this.attributes.parcelMapBook = responseData.attributes.parcel_map_book; - this.attributes.parcelMapPage = responseData.attributes.parcel_map_page; - this.attributes.parcelNumberAlternate = responseData.attributes.parcel_number_alternate; - this.attributes.parcelNumberFormatted = responseData.attributes.parcel_number_formatted; - this.attributes.parcelNumberPrevious = responseData.attributes.parcel_number_previous; - this.attributes.parcelNumberYearAdded = responseData.attributes.parcel_number_year_added; - this.attributes.parcelNumberYearChange = responseData.attributes.parcel_number_year_change; - this.attributes.parcelRawNumber = responseData.attributes.parcel_raw_number; - this.attributes.parcelShellRecord = responseData.attributes.parcel_shell_record; - this.attributes.parkingSpaces = responseData.attributes.parking_spaces; - this.attributes.patioArea = responseData.attributes.patio_area; - this.attributes.phaseName = responseData.attributes.phase_name; - this.attributes.plumbingFixturesCount = responseData.attributes.plumbing_fixtures_count; - this.attributes.poleStruct = responseData.attributes.pole_struct; - this.attributes.poleStructSqft = responseData.attributes.pole_struct_sqft; - this.attributes.pond = responseData.attributes.pond; - this.attributes.pool = responseData.attributes.pool; - this.attributes.poolArea = responseData.attributes.pool_area; - this.attributes.poolhouse = responseData.attributes.poolhouse; - this.attributes.poolhouseSqft = responseData.attributes.poolhouse_sqft; - this.attributes.porch = responseData.attributes.porch; - this.attributes.porchArea = responseData.attributes.porch_area; - this.attributes.poultryHouse = responseData.attributes.poultry_house; - this.attributes.poultryHouseSqft = responseData.attributes.poultry_house_sqft; - this.attributes.previousAssessedValue = responseData.attributes.previous_assessed_value; - this.attributes.priorSaleAmount = responseData.attributes.prior_sale_amount; - this.attributes.priorSaleDate = responseData.attributes.prior_sale_date; - this.attributes.propertyAddressCarrierRouteCode = responseData.attributes.property_address_carrier_route_code; - this.attributes.propertyAddressCity = responseData.attributes.property_address_city; - this.attributes.propertyAddressFull = responseData.attributes.property_address_full; - this.attributes.propertyAddressHouseNumber = responseData.attributes.property_address_house_number; - this.attributes.propertyAddressPostDirection = responseData.attributes.property_address_post_direction; - this.attributes.propertyAddressPreDirection = responseData.attributes.property_address_pre_direction; - this.attributes.propertyAddressState = responseData.attributes.property_address_state; - this.attributes.propertyAddressStreetName = responseData.attributes.property_address_street_name; - this.attributes.propertyAddressStreetSuffix = responseData.attributes.property_address_street_suffix; - this.attributes.propertyAddressUnitDesignator = responseData.attributes.property_address_unit_designator; - this.attributes.propertyAddressUnitValue = responseData.attributes.property_address_unit_value; - this.attributes.propertyAddressZip4 = responseData.attributes.property_address_zip_4; - this.attributes.propertyAddressZipcode = responseData.attributes.property_address_zipcode; - this.attributes.publicationDate = responseData.attributes.publication_date; - this.attributes.quarter = responseData.attributes.quarter; - this.attributes.quarterQuarter = responseData.attributes.quarter_quarter; - this.attributes.quonset = responseData.attributes.quonset; - this.attributes.quonsetSqft = responseData.attributes.quonset_sqft; - this.attributes.range = responseData.attributes.range; - this.attributes.recordingDate = responseData.attributes.recording_date; - this.attributes.roofCover = responseData.attributes.roof_cover; - this.attributes.roofFrame = responseData.attributes.roof_frame; - this.attributes.rooms = responseData.attributes.rooms; - this.attributes.rvParking = responseData.attributes.rv_parking; - this.attributes.safeRoom = responseData.attributes.safe_room; - this.attributes.saleAmount = responseData.attributes.sale_amount; - this.attributes.saleDate = responseData.attributes.sale_date; - this.attributes.sauna = responseData.attributes.sauna; - this.attributes.section = responseData.attributes.section; - this.attributes.securityAlarm = responseData.attributes.security_alarm; - this.attributes.seniorTaxExemption = responseData.attributes.senior_tax_exemption; - this.attributes.sewerType = responseData.attributes.sewer_type; - this.attributes.shed = responseData.attributes.shed; - this.attributes.shedSqft = responseData.attributes.shed_sqft; - this.attributes.silo = responseData.attributes.silo; - this.attributes.siloSqft = responseData.attributes.silo_sqft; - this.attributes.sittingRoom = responseData.attributes.sitting_room; - this.attributes.situsCounty = responseData.attributes.situs_county; - this.attributes.situsState = responseData.attributes.situs_state; - this.attributes.soundSystem = responseData.attributes.sound_system; - this.attributes.sportsCourt = responseData.attributes.sports_court; - this.attributes.sprinklers = responseData.attributes.sprinklers; - this.attributes.stable = responseData.attributes.stable; - this.attributes.stableSqft = responseData.attributes.stable_sqft; - this.attributes.storageBuilding = responseData.attributes.storage_building; - this.attributes.storageBuildingSqft = responseData.attributes.storage_buildling_sqft; - this.attributes.storiesNumber = responseData.attributes.stories_number; - this.attributes.stormShelter = responseData.attributes.storm_shelter; - this.attributes.stormShutter = responseData.attributes.storm_shutter; - this.attributes.structureStyle = responseData.attributes.structure_style; - this.attributes.study = responseData.attributes.study; - this.attributes.subdivision = responseData.attributes.subdivision; - this.attributes.suffix = responseData.attributes.suffix; - this.attributes.suffix2 = responseData.attributes.suffix_2; - this.attributes.suffix3 = responseData.attributes.suffix_3; - this.attributes.suffix4 = responseData.attributes.suffix_4; - this.attributes.sunroom = responseData.attributes.sunroom; - this.attributes.taxAssessYear = responseData.attributes.tax_assess_year; - this.attributes.taxBilledAmount = responseData.attributes.tax_billed_amount; - this.attributes.taxDelinquentYear = responseData.attributes.tax_delinquent_year; - this.attributes.taxFiscalYear = responseData.attributes.tax_fiscal_year; - this.attributes.taxJurisdiction = responseData.attributes.tax_jurisdiction; - this.attributes.taxRateArea = responseData.attributes.tax_rate_area; - this.attributes.tennisCourt = responseData.attributes.tennis_court; - this.attributes.topographyCode = responseData.attributes.topography_code; - this.attributes.totalMarketValue = responseData.attributes.total_market_value; - this.attributes.township = responseData.attributes.township; - this.attributes.tractNumber = responseData.attributes.tract_number; - this.attributes.transferAmount = responseData.attributes.transfer_amount; - this.attributes.trustDescription = responseData.attributes.trust_description; - this.attributes.unitCount = responseData.attributes.unit_count; - this.attributes.upperFloorsSqft = responseData.attributes.upper_floors_sqft; - this.attributes.utility = responseData.attributes.utility; - this.attributes.utilityBuilding = responseData.attributes.utility_building; - this.attributes.utilityBuildingSqft = responseData.attributes.utility_building_sqft; - this.attributes.utilitySqft = responseData.attributes.utility_sqft; - this.attributes.veteranTaxExemption = responseData.attributes.veteran_tax_exemption; - this.attributes.viewDescription = responseData.attributes.view_description; - this.attributes.waterFeature = responseData.attributes.water_feature; - this.attributes.waterServiceType = responseData.attributes.water_service_type; - this.attributes.wetBar = responseData.attributes.wet_bar; - this.attributes.widowTaxExemption = responseData.attributes.widow_tax_exemption; - this.attributes.widthLinearFootage = responseData.attributes.width_linear_footage; - this.attributes.wineCellar = responseData.attributes.wine_cellar; - this.attributes.yearBuilt = responseData.attributes.year_built; - this.attributes.zoning = responseData.attributes.zoning; - } - } -} - -class FinancialResponse { - constructor(responseData) { - this.smartyKey = responseData.smarty_key; - this.dataSetName = responseData.data_set_name; - this.dataSubsetName = responseData.data_subset_name; - - this.attributes = {}; - if (responseData.attributes) { - this.attributes.assessedImprovementPercent = responseData.attributes.assessed_improvement_percent; - this.attributes.assessedImprovementValue = responseData.attributes.assessed_improvement_value; - this.attributes.assessedLandValue = responseData.attributes.assessed_land_value; - this.attributes.assessedValue = responseData.attributes.assessed_value; - this.attributes.assessorLastUpdate = responseData.attributes.assessor_last_update; - this.attributes.assessorTaxrollUpdate = responseData.attributes.assessor_taxroll_update; - this.attributes.contactCity = responseData.attributes.contact_city; - this.attributes.contactCrrt = responseData.attributes.contact_crrt; - this.attributes.contactFullAddress = responseData.attributes.contact_full_address; - this.attributes.contactHouseNumber = responseData.attributes.contact_house_number; - this.attributes.contactMailInfoFormat = responseData.attributes.contact_main_info_format; - this.attributes.contactMailInfoPrivacy = responseData.attributes.contact_mail_info_privacy; - this.attributes.contactMailingCounty = responseData.attributes.contact_mailing_county; - this.attributes.contactMailingFips = responseData.attributes.contact_mailing_fips; - this.attributes.contactPostDirection = responseData.attributes.contact_post_direction; - this.attributes.contactPreDirection = responseData.attributes.contact_pre_direction; - this.attributes.contactState = responseData.attributes.contact_state; - this.attributes.contactStreetName = responseData.attributes.contact_street_name; - this.attributes.contactSuffix = responseData.attributes.contact_suffix; - this.attributes.contactUnitDesignator = responseData.attributes.contact_unit_designator; - this.attributes.contactValue = responseData.attributes.contact_value; - this.attributes.contactZip = responseData.attributes.contact_zip; - this.attributes.contactZip4 = responseData.attributes.contact_zip4; - this.attributes.deedDocumentPage = responseData.attributes.deed_document_page; - this.attributes.deedDocumentBook = responseData.attributes.deed_document_book; - this.attributes.deedDocumentNumber = responseData.attributes.deed_document_number; - this.attributes.deedOwnerFirstName = responseData.attributes.deed_owner_first_name; - this.attributes.deedOwnerFirstName2 = responseData.attributes.deed_owner_first_name2; - this.attributes.deedOwnerFirstName3 = responseData.attributes.deed_owner_first_name3; - this.attributes.deedOwnerFirstName4 = responseData.attributes.deed_owner_first_name4; - this.attributes.deedOwnerFullName = responseData.attributes.deed_owner_full_name; - this.attributes.deedOwnerFullName2 = responseData.attributes.deed_owner_full_name2; - this.attributes.deedOwnerFullName3 = responseData.attributes.deed_owner_full_name3; - this.attributes.deedOwnerFullName4 = responseData.attributes.deed_owner_full_name4; - this.attributes.deedOwnerLastName = responseData.attributes.deed_owner_last_name; - this.attributes.deedOwnerLastName2 = responseData.attributes.deed_owner_last_name2; - this.attributes.deedOwnerLastName3 = responseData.attributes.deed_owner_last_name3; - this.attributes.deedOwnerLastName4 = responseData.attributes.deed_owner_last_name4; - this.attributes.deedOwnerMiddleName = responseData.attributes.deed_owner_middle_name; - this.attributes.deedOwnerMiddleName2 = responseData.attributes.deed_owner_middle_name2; - this.attributes.deedOwnerMiddleName3 = responseData.attributes.deed_owner_middle_name3; - this.attributes.deedOwnerMiddleName4 = responseData.attributes.deed_owner_middle_name4; - this.attributes.deedOwnerSuffix = responseData.attributes.deed_owner_suffix; - this.attributes.deedOwnerSuffix2 = responseData.attributes.deed_owner_suffix2; - this.attributes.deedOwnerSuffix3 = responseData.attributes.deed_owner_suffix3; - this.attributes.deedOwnerSuffix4 = responseData.attributes.deed_owner_suffix4; - this.attributes.deedSaleDate = responseData.attributes.deed_sale_date; - this.attributes.deedSalePrice = responseData.attributes.deed_sale_price; - this.attributes.deedTransactionId = responseData.attributes.deed_transaction_id; - this.attributes.disabledTaxExemption = responseData.attributes.disabled_tax_exemption; - - this.attributes.financialHistory = !responseData.attributes.financial_history ? [] : responseData.attributes.financial_history.map(history => { - return { - codeTitleCompany: history.code_title_company, - instrumentDate: history.instrument_date, - interestRateType2: history.interest_rate_type_2, - lenderAddress: history.lender_address, - lenderAddress2: history.lender_address_2, - lenderCity: history.lender_city, - lenderCity2: history.lender_city_2, - lenderCode: history.lender_code, - lenderCode2: history.lender_code_2, - lenderFirstName: history.lender_first_name, - lenderFirstName2: history.lender_first_name_2, - lenderLastName: history.lender_last_name, - lenderLastName2: history.lender_last_name_2, - lenderName: history.lender_name, - lenderName2: history.lender_name_2, - lenderSellerCarryBack: history.lender_seller_carry_back, - lenderSellerCarryBack2: history.lender_seller_carry_back_2, - lenderState: history.lender_state, - lenderState2: history.lender_state_2, - lenderZip: history.lender_zip, - lenderZip2: history.lender_zip_2, - lenderZipExtended: history.lender_zip_extended, - lenderZipExtended2: history.lender_zip_extended_2, - mortgageAmount: history.mortgage_amount, - mortgageAmount2: history.mortgage_amount_2, - mortgageDueDate: history.mortgage_due_date, - mortgageDueDate2: history.mortgage_due_date_2, - mortgageInterestRate: history.mortgage_interest_rate, - mortgageInterestRateType: history.mortgage_interest_rate_type, - mortgageLenderCode: history.mortgage_lender_code, - mortgageRate: history.mortgage_rate, - mortgageRate2: history.mortgage_rate_2, - mortgageRecordingDate: history.mortgage_recording_date, - mortgageRecordingDate2: history.mortgage_recording_date_2, - mortgageTerm: history.mortgage_term, - mortgageTerm2: history.mortgage_term_2, - mortgageTermType: history.mortgage_term_type, - mortgageTermType2: history.mortgage_term_type_2, - mortgageType: history.mortgage_type, - mortgageType2: history.mortgage_type_2, - multiParcelFlag: history.multi_parcel_flag, - nameTitleCompany: history.name_title_company, - recordingDate: history.recording_date, - transferAmount: history.transfer_amount, - } - }) - this.attributes.homeownerTaxExemption = responseData.attributes.homeowner_tax_exemption; - this.attributes.marketImprovementPercent = responseData.attributes.market_improvement_percent; - this.attributes.marketImprovementValue = responseData.attributes.market_improvement_value; - this.attributes.marketLandValue = responseData.attributes.market_land_value; - this.attributes.marketValueYear = responseData.attributes.market_value_year; - this.attributes.matchType = responseData.attributes.match_type; - this.attributes.otherTaxExemption = responseData.attributes.other_tax_exemption; - this.attributes.ownershipTransferDate = responseData.attributes.ownership_transfer_date; - this.attributes.ownershipTransferDocNumber = responseData.attributes.ownership_transfer_doc_number; - this.attributes.ownershipTransferTransactionId = responseData.attributes.ownership_transfer_transaction_id; - this.attributes.ownershipType = responseData.attributes.ownership_type; - this.attributes.ownershipType2 = responseData.attributes.ownership_type_2; - this.attributes.previousAssessedValue = responseData.attributes.previous_assessed_value; - this.attributes.priorSaleAmount = responseData.attributes.prior_sale_amount; - this.attributes.priorSaleDate = responseData.attributes.prior_sale_date; - this.attributes.saleAmount = responseData.attributes.sale_amount; - this.attributes.saleDate = responseData.attributes.sale_date; - this.attributes.seniorTaxExemption = responseData.attributes.senior_tax_exemption; - this.attributes.taxAssessYear = responseData.attributes.tax_assess_year; - this.attributes.taxBilledAmount = responseData.attributes.tax_billed_amount; - this.attributes.taxDelinquentYear = responseData.attributes.tax_delinquent_year; - this.attributes.taxFiscalYear = responseData.attributes.tax_fiscal_year; - this.attributes.taxRateArea = responseData.attributes.tax_rate_area; - this.attributes.totalMarketValue = responseData.attributes.total_market_value; - this.attributes.trustDescription = responseData.attributes.trust_description; - this.attributes.veteranTaxExemption = responseData.attributes.veteran_tax_exemption; - this.attributes.widow_tax_exemption = responseData.attributes.widow_tax_exemption; - } - } -} - -class GeoResponse { - constructor(responseData) { - this.smartyKey = responseData.smarty_key; - this.dataSetName = responseData.data_set_name; - - this.attributes = {}; - if (responseData.attributes) { - this.attributes.censusBlock = {}; - if (responseData.attributes.census_block) { - this.attributes.censusBlock.accuracy = responseData.attributes.census_block.accuracy; - this.attributes.censusBlock.geoid = responseData.attributes.census_block.geoid; - } - - this.attributes.censusCountyDivision = {}; - if (responseData.attributes.census_county_division) { - this.attributes.censusCountyDivision.accuracy = responseData.attributes.census_county_division.accuracy; - this.attributes.censusCountyDivision.code = responseData.attributes.census_county_division.code; - this.attributes.censusCountyDivision.name = responseData.attributes.census_county_division.name; - } - - this.attributes.censusTract = {}; - if (responseData.attributes.census_tract) { - this.attributes.censusTract.code = responseData.attributes.census_tract.code; - } - - this.attributes.coreBasedStatArea = {}; - if (responseData.attributes.core_based_stat_area) { - this.attributes.coreBasedStatArea.code = responseData.attributes.core_based_stat_area.code; - this.attributes.coreBasedStatArea.name = responseData.attributes.core_based_stat_area.name; - } - - this.attributes.place = {}; - if (responseData.attributes.place) { - this.attributes.place.accuracy = responseData.attributes.place.accuracy; - this.attributes.place.code = responseData.attributes.place.code; - this.attributes.place.name = responseData.attributes.place.name; - this.attributes.place.type = responseData.attributes.place.type; - } - } - } -} - -module.exports = { - Response, - FinancialResponse, - GeoResponse, -}; \ No newline at end of file diff --git a/src/us_enrichment/Response.ts b/src/us_enrichment/Response.ts new file mode 100644 index 0000000..9775a7f --- /dev/null +++ b/src/us_enrichment/Response.ts @@ -0,0 +1,1720 @@ +export interface FinancialHistory { + codeTitleCompany: string | undefined; + instrumentDate: string | undefined; + interestRateType2: string | undefined; + lenderAddress: string | undefined; + lenderAddress2: string | undefined; + lenderCity: string | undefined; + lenderCity2: string | undefined; + lenderCode: string | undefined; + lenderCode2: string | undefined; + lenderFirstName: string | undefined; + lenderFirstName2: string | undefined; + lenderLastName: string | undefined; + lenderLastName2: string | undefined; + lenderName: string | undefined; + lenderName2: string | undefined; + lenderSellerCarryBack: string | undefined; + lenderSellerCarryBack2: string | undefined; + lenderState: string | undefined; + lenderState2: string | undefined; + lenderZip: string | undefined; + lenderZip2: string | undefined; + lenderZipExtended: string | undefined; + lenderZipExtended2: string | undefined; + mortgageAmount: string | undefined; + mortgageAmount2: string | undefined; + mortgageDueDate: string | undefined; + mortgageDueDate2: string | undefined; + mortgageInterestRate: string | undefined; + mortgageInterestRateType: string | undefined; + mortgageLenderCode: string | undefined; + mortgageRate: string | undefined; + mortgageRate2: string | undefined; + mortgageRecordingDate: string | undefined; + mortgageRecordingDate2: string | undefined; + mortgageTerm: string | undefined; + mortgageTerm2: string | undefined; + mortgageTermType: string | undefined; + mortgageTermType2: string | undefined; + mortgageType: string | undefined; + mortgageType2: string | undefined; + multiParcelFlag: string | undefined; + nameTitleCompany: string | undefined; + recordingDate: string | undefined; + transferAmount: string | undefined; +} + +interface RawFinancialHistory { + code_title_company?: string; + instrument_date?: string; + interest_rate_type_2?: string; + lender_address?: string; + lender_address_2?: string; + lender_city?: string; + lender_city_2?: string; + lender_code?: string; + lender_code_2?: string; + lender_first_name?: string; + lender_first_name_2?: string; + lender_last_name?: string; + lender_last_name_2?: string; + lender_name?: string; + lender_name_2?: string; + lender_seller_carry_back?: string; + lender_seller_carry_back_2?: string; + lender_state?: string; + lender_state_2?: string; + lender_zip?: string; + lender_zip_2?: string; + lender_zip_extended?: string; + lender_zip_extended_2?: string; + mortgage_amount?: string; + mortgage_amount_2?: string; + mortgage_due_date?: string; + mortgage_due_date_2?: string; + mortgage_interest_rate?: string; + mortgage_interest_rate_type?: string; + mortgage_lender_code?: string; + mortgage_rate?: string; + mortgage_rate_2?: string; + mortgage_recording_date?: string; + mortgage_recording_date_2?: string; + mortgage_term?: string; + mortgage_term_2?: string; + mortgage_term_type?: string; + mortgage_term_type_2?: string; + mortgage_type?: string; + mortgage_type_2?: string; + multi_parcel_flag?: string; + name_title_company?: string; + recording_date?: string; + transfer_amount?: string; +} + +export interface EnrichmentAttributes { + firstFloorSqft: string | undefined; + secondFloorSqft: string | undefined; + acres: string | undefined; + addressInfoPrivacy: string | undefined; + airConditioner: string | undefined; + arborPergola: string | undefined; + assessedImprovementPercent: string | undefined; + assessedImprovementValue: string | undefined; + assessedLandValue: string | undefined; + assessedValue: string | undefined; + assessorLastUpdate: string | undefined; + assessorTaxrollUpdate: string | undefined; + atticArea: string | undefined; + atticFlag: string | undefined; + balcony: string | undefined; + balconyArea: string | undefined; + basementSqft: string | undefined; + basementSqftFinished: string | undefined; + basementsqftUnfinished: string | undefined; + bathHouse: string | undefined; + bathHouseSqft: string | undefined; + bathroomsPartial: string | undefined; + bathroomsTotal: string | undefined; + bedrooms: string | undefined; + block1: string | undefined; + block2: string | undefined; + boatAccess: string | undefined; + boatHouse: string | undefined; + boatHouseSqft: string | undefined; + boatLift: string | undefined; + bonusRoom: string | undefined; + breakfastNook: string | undefined; + breezeway: string | undefined; + buildingDefinitionCode: string | undefined; + buildingSqft: string | undefined; + cabin: string | undefined; + cabinSqft: string | undefined; + canopy: string | undefined; + canopySqft: string | undefined; + carport: string | undefined; + carportSqft: string | undefined; + cbsaCode: string | undefined; + cbsaName: string | undefined; + cellar: string | undefined; + censusBlock: string | undefined; + censusTract: string | undefined; + censusBlockGroup: string | undefined; + censusFipsPlaceCode: string | undefined; + centralVacuum: string | undefined; + codeTitleCompany: string | undefined; + combinedStatisticalArea: string | undefined; + communityRec: string | undefined; + companyFlag: string | undefined; + congressionalDistrict: string | undefined; + constructionType: string | undefined; + contactCity: string | undefined; + contactCrrt: string | undefined; + contactFullAddress: string | undefined; + contactHouseNumber: string | undefined; + contactMailInfoFormat: string | undefined; + contactMailInfoPrivacy: string | undefined; + contactMailingCounty: string | undefined; + contactMailingFips: string | undefined; + contactPostDirection: string | undefined; + contactPreDirection: string | undefined; + contactState: string | undefined; + contactStreetName: string | undefined; + contactSuffix: string | undefined; + contactUnitDesignator: string | undefined; + contactValue: string | undefined; + contactZip: string | undefined; + contactZip4: string | undefined; + courtyard: string | undefined; + courtyardArea: string | undefined; + deck: string | undefined; + deckArea: string | undefined; + deedDocumentPage: string | undefined; + deedDocumentBook: string | undefined; + deedDocumentNumber: string | undefined; + deedOwnerFirstName: string | undefined; + deedOwnerFirstName2: string | undefined; + deedOwnerFirstName3: string | undefined; + deedOwnerFirstName4: string | undefined; + deedOwnerFullName: string | undefined; + deedOwnerFullName2: string | undefined; + deedOwnerFullName3: string | undefined; + deedOwnerFullName4: string | undefined; + deedOwnerLastName: string | undefined; + deedOwnerLastName2: string | undefined; + deedOwnerLastName3: string | undefined; + deedOwnerLastName4: string | undefined; + deedOwnerMiddleName: string | undefined; + deedOwnerMiddleName2: string | undefined; + deedOwnerMiddleName3: string | undefined; + deedOwnerMiddleName4: string | undefined; + deedOwnerSuffix: string | undefined; + deedOwnerSuffix2: string | undefined; + deedOwnerSuffix3: string | undefined; + deedOwnerSuffix4: string | undefined; + deedSaleDate: string | undefined; + deedSalePrice: string | undefined; + deedTransactionId: string | undefined; + depthLinearFootage: string | undefined; + disabledTaxExemption: string | undefined; + drivewaySqft: string | undefined; + drivewayType: string | undefined; + effectiveYearBuilt: string | undefined; + elevationFeet: string | undefined; + elevator: string | undefined; + equestrianArena: string | undefined; + escalator: string | undefined; + exerciseRoom: string | undefined; + exteriorWalls: string | undefined; + familyRoom: string | undefined; + fence: string | undefined; + fenceArea: string | undefined; + fipsCode: string | undefined; + fireResistanceCode: string | undefined; + fireSprinklersFlag: string | undefined; + fireplace: string | undefined; + fireplaceNumber: string | undefined; + firstName: string | undefined; + firstName2: string | undefined; + firstName3: string | undefined; + firstName4: string | undefined; + flooring: string | undefined; + foundation: string | undefined; + gameRoom: string | undefined; + garage: string | undefined; + garageSqft: string | undefined; + gazebo: string | undefined; + gazeboSqft: string | undefined; + golfCourse: string | undefined; + grainery: string | undefined; + grainerySqft: string | undefined; + greatRoom: string | undefined; + greenhouse: string | undefined; + greenhouseSqft: string | undefined; + grossSqft: string | undefined; + guesthouse: string | undefined; + guesthouseSqft: string | undefined; + handicapAccessibility: string | undefined; + heat: string | undefined; + heatFuelType: string | undefined; + hobbyRoom: string | undefined; + homeownerTaxExemption: string | undefined; + instrumentDate: string | undefined; + intercomSystem: string | undefined; + interestRateType2: string | undefined; + interiorStructure: string | undefined; + kennel: string | undefined; + kennelSqft: string | undefined; + landUseCode: string | undefined; + landUseGroup: string | undefined; + landUseStandard: string | undefined; + lastName: string | undefined; + lastName2: string | undefined; + lastName3: string | undefined; + lastName4: string | undefined; + latitude: string | undefined; + laundry: string | undefined; + leanTo: string | undefined; + leanToSqft: string | undefined; + legalDescription: string | undefined; + legalUnit: string | undefined; + lenderAddress: string | undefined; + lenderAddress2: string | undefined; + lenderCity: string | undefined; + lenderCity2: string | undefined; + lenderCode: string | undefined; + lenderCode2: string | undefined; + lenderFirstName: string | undefined; + lenderFirstName2: string | undefined; + lenderLastName: string | undefined; + lenderLastName2: string | undefined; + lenderName: string | undefined; + lenderName2: string | undefined; + lenderSellerCarryBack: string | undefined; + lenderSellerCarryBack2: string | undefined; + lenderState: string | undefined; + lenderState2: string | undefined; + lenderZip: string | undefined; + lenderZip2: string | undefined; + lenderZipExtended: string | undefined; + lenderZipExtended2: string | undefined; + loadingPlatform: string | undefined; + loadingPlatformSqft: string | undefined; + longitude: string | undefined; + lot1: string | undefined; + lot2: string | undefined; + lot3: string | undefined; + lotSqft: string | undefined; + marketImprovementPercent: string | undefined; + marketImprovementValue: string | undefined; + marketLandValue: string | undefined; + marketValueYear: string | undefined; + matchType: string | undefined; + mediaRoom: string | undefined; + metroDivision: string | undefined; + middleName: string | undefined; + middleName2: string | undefined; + middleName3: string | undefined; + middleName4: string | undefined; + milkhouse: string | undefined; + milkhouseSqft: string | undefined; + minorCivilDivisionCode: string | undefined; + minorCivilDivisionName: string | undefined; + mobileHomeHookup: string | undefined; + mortgageAmount: string | undefined; + mortgageAmount2: string | undefined; + mortgageDueDate: string | undefined; + mortgageDueDate2: string | undefined; + mortgageInterestRate: string | undefined; + mortgageInterestRateType: string | undefined; + mortgageLenderCode: string | undefined; + mortgageRate2: string | undefined; + mortgageRecordingDate: string | undefined; + mortgageRecordingDate2: string | undefined; + mortgageTerm: string | undefined; + mortgageTerm2: string | undefined; + mortgageTermType: string | undefined; + mortgageTermType2: string | undefined; + mortgageType: string | undefined; + mortgageType2: string | undefined; + msaCode: string | undefined; + msaName: string | undefined; + mudRoom: string | undefined; + multiParcelFlag: string | undefined; + nameTitleCompany: string | undefined; + neighborhoodCode: string | undefined; + numberOfBuildings: string | undefined; + office: string | undefined; + officeSqft: string | undefined; + otherTaxExemption: string | undefined; + outdoorKitchenFireplace: string | undefined; + overheadDoor: string | undefined; + ownerFullName: string | undefined; + ownerFullName2: string | undefined; + ownerFullName3: string | undefined; + ownerFullName4: string | undefined; + ownerOccupancyStatus: string | undefined; + ownershipTransferDate: string | undefined; + ownershipTransferDocNumber: string | undefined; + ownershipTransferTransactionId: string | undefined; + ownershipType: string | undefined; + ownershipType2: string | undefined; + ownershipVestingRelationCode: string | undefined; + parcelAccountNumber: string | undefined; + parcelMapBook: string | undefined; + parcelMapPage: string | undefined; + parcelNumberAlternate: string | undefined; + parcelNumberFormatted: string | undefined; + parcelNumberPrevious: string | undefined; + parcelNumberYearAdded: string | undefined; + parcelNumberYearChange: string | undefined; + parcelRawNumber: string | undefined; + parcelShellRecord: string | undefined; + parkingSpaces: string | undefined; + patioArea: string | undefined; + phaseName: string | undefined; + plumbingFixturesCount: string | undefined; + poleStruct: string | undefined; + poleStructSqft: string | undefined; + pond: string | undefined; + pool: string | undefined; + poolArea: string | undefined; + poolhouse: string | undefined; + poolhouseSqft: string | undefined; + porch: string | undefined; + porchArea: string | undefined; + poultryHouse: string | undefined; + poultryHouseSqft: string | undefined; + previousAssessedValue: string | undefined; + priorSaleAmount: string | undefined; + priorSaleDate: string | undefined; + propertyAddressCarrierRouteCode: string | undefined; + propertyAddressCity: string | undefined; + propertyAddressFull: string | undefined; + propertyAddressHouseNumber: string | undefined; + propertyAddressPostDirection: string | undefined; + propertyAddressPreDirection: string | undefined; + propertyAddressState: string | undefined; + propertyAddressStreetName: string | undefined; + propertyAddressStreetSuffix: string | undefined; + propertyAddressUnitDesignator: string | undefined; + propertyAddressUnitValue: string | undefined; + propertyAddressZip4: string | undefined; + propertyAddressZipcode: string | undefined; + publicationDate: string | undefined; + quarter: string | undefined; + quarterQuarter: string | undefined; + quonset: string | undefined; + quonsetSqft: string | undefined; + range: string | undefined; + recordingDate: string | undefined; + roofCover: string | undefined; + roofFrame: string | undefined; + rooms: string | undefined; + rvParking: string | undefined; + safeRoom: string | undefined; + saleAmount: string | undefined; + saleDate: string | undefined; + sauna: string | undefined; + section: string | undefined; + securityAlarm: string | undefined; + seniorTaxExemption: string | undefined; + sewerType: string | undefined; + shed: string | undefined; + shedSqft: string | undefined; + silo: string | undefined; + siloSqft: string | undefined; + sittingRoom: string | undefined; + situsCounty: string | undefined; + situsState: string | undefined; + soundSystem: string | undefined; + sportsCourt: string | undefined; + sprinklers: string | undefined; + stable: string | undefined; + stableSqft: string | undefined; + storageBuilding: string | undefined; + storageBuildingSqft: string | undefined; + storiesNumber: string | undefined; + stormShelter: string | undefined; + stormShutter: string | undefined; + structureStyle: string | undefined; + study: string | undefined; + subdivision: string | undefined; + suffix: string | undefined; + suffix2: string | undefined; + suffix3: string | undefined; + suffix4: string | undefined; + sunroom: string | undefined; + taxAssessYear: string | undefined; + taxBilledAmount: string | undefined; + taxDelinquentYear: string | undefined; + taxFiscalYear: string | undefined; + taxJurisdiction: string | undefined; + taxRateArea: string | undefined; + tennisCourt: string | undefined; + topographyCode: string | undefined; + totalMarketValue: string | undefined; + township: string | undefined; + tractNumber: string | undefined; + transferAmount: string | undefined; + trustDescription: string | undefined; + unitCount: string | undefined; + upperFloorsSqft: string | undefined; + utility: string | undefined; + utilityBuilding: string | undefined; + utilityBuildingSqft: string | undefined; + utilitySqft: string | undefined; + veteranTaxExemption: string | undefined; + viewDescription: string | undefined; + waterFeature: string | undefined; + waterServiceType: string | undefined; + wetBar: string | undefined; + widowTaxExemption: string | undefined; + widthLinearFootage: string | undefined; + wineCellar: string | undefined; + financialHistory: FinancialHistory[]; + yearBuilt: string | undefined; + zoning: string | undefined; +} + +interface RawEnrichmentAttributes { + "1st_floor_sqft"?: string; + "2nd_floor_sqft"?: string; + acres?: string; + address_info_privacy?: string; + air_conditioner?: string; + arbor_pergola?: string; + assessed_improvement_percent?: string; + assessed_improvement_value?: string; + assessed_land_value?: string; + assessed_value?: string; + assessor_last_update?: string; + assessor_taxroll_update?: string; + attic_area?: string; + attic_flag?: string; + balcony?: string; + balcony_area?: string; + basement_sqft?: string; + basement_sqft_finished?: string; + basement_sqft_unfinished?: string; + bath_house?: string; + bath_house_sqft?: string; + bathrooms_partial?: string; + bathrooms_total?: string; + bedrooms?: string; + block_1?: string; + block_2?: string; + boat_access?: string; + boat_house?: string; + boat_house_sqft?: string; + boat_lift?: string; + bonus_room?: string; + breakfast_nook?: string; + breezeway?: string; + building_definition?: string; + building_sqft?: string; + cabin?: string; + cabin_sqft?: string; + canopy?: string; + canopy_sqft?: string; + carport?: string; + carport_sqft?: string; + cbsa_code?: string; + cbsa_name?: string; + cellar?: string; + census_block?: string; + census_tract?: string; + census_block_group?: string; + census_fips_place_code?: string; + central_vacuum?: string; + code_title_company?: string; + combined_statistical_area?: string; + community_rec?: string; + company_flag?: string; + congressional_district?: string; + construction_type?: string; + contact_city?: string; + contact_crrt?: string; + contact_full_address?: string; + contact_house_number?: string; + contact_main_info_format?: string; + contact_mail_info_privacy?: string; + contact_mailing_county?: string; + contact_mailing_fips?: string; + contact_post_direction?: string; + contact_pre_direction?: string; + contact_state?: string; + contact_street_name?: string; + contact_suffix?: string; + contact_unit_designator?: string; + contact_value?: string; + contact_zip?: string; + contact_zip4?: string; + courtyard?: string; + courtyard_area?: string; + deck?: string; + deck_area?: string; + deed_document_page?: string; + deed_document_book?: string; + deed_document_number?: string; + deed_owner_first_name?: string; + deed_owner_first_name2?: string; + deed_owner_first_name3?: string; + deed_owner_first_name4?: string; + deed_owner_full_name?: string; + deed_owner_full_name2?: string; + deed_owner_full_name3?: string; + deed_owner_full_name4?: string; + deed_owner_last_name?: string; + deed_owner_last_name2?: string; + deed_owner_last_name3?: string; + deed_owner_last_name4?: string; + deed_owner_middle_name?: string; + deed_owner_middle_name2?: string; + deed_owner_middle_name3?: string; + deed_owner_middle_name4?: string; + deed_owner_suffix?: string; + deed_owner_suffix2?: string; + deed_owner_suffix3?: string; + deed_owner_suffix4?: string; + deed_sale_date?: string; + deed_sale_price?: string; + deed_transaction_id?: string; + depth_linear_footage?: string; + disabled_tax_exemption?: string; + driveway_sqft?: string; + driveway_type?: string; + effective_year_built?: string; + elevation_feet?: string; + elevator?: string; + equestrian_arena?: string; + escalator?: string; + exercise_room?: string; + exterior_walls?: string; + family_room?: string; + fence?: string; + fence_area?: string; + fips_code?: string; + fire_resistance_code?: string; + fire_sprinkler_flag?: string; + fireplace?: string; + fireplace_number?: string; + first_name?: string; + first_name2?: string; + first_name3?: string; + first_name4?: string; + flooring?: string; + foundation?: string; + game_room?: string; + garage?: string; + garage_sqft?: string; + gazebo?: string; + gazebo_sqft?: string; + golf_course?: string; + grainery?: string; + grainery_sqft?: string; + great_room?: string; + greenhouse?: string; + greenhouse_sqft?: string; + gross_sqft?: string; + guesthouse?: string; + guesthouse_sqft?: string; + handicap_accessibility?: string; + heat?: string; + heat_fuel_type?: string; + hobby_room?: string; + homeowner_tax_exemption?: string; + instrument_date?: string; + intercom_system?: string; + interest_rate_type_2?: string; + interior_structure?: string; + kennel?: string; + kennel_sqft?: string; + land_use_code?: string; + land_use_group?: string; + land_use_standard?: string; + last_name?: string; + last_name_2?: string; + last_name_3?: string; + last_name_4?: string; + latitude?: string; + laundry?: string; + lean_to?: string; + lean_to_sqft?: string; + legal_description?: string; + legal_unit?: string; + lender_address?: string; + lender_address_2?: string; + lender_city?: string; + lender_city_2?: string; + lender_code?: string; + lender_code_2?: string; + lender_first_name?: string; + lender_first_name_2?: string; + lender_last_name?: string; + lender_last_name_2?: string; + lender_name?: string; + lender_name_2?: string; + lender_seller_carry_back?: string; + lender_seller_carry_back_2?: string; + lender_state?: string; + lender_state_2?: string; + lender_zip?: string; + lender_zip_2?: string; + lender_zip_extended?: string; + lender_zip_extended_2?: string; + loading_platform?: string; + loading_platform_sqft?: string; + longitude?: string; + lot_1?: string; + lot_2?: string; + lot_3?: string; + lot_sqft?: string; + market_improvement_percent?: string; + market_improvement_value?: string; + market_land_value?: string; + market_value_year?: string; + match_type?: string; + media_room?: string; + metro_division?: string; + middle_name?: string; + middle_name_2?: string; + middle_name_3?: string; + middle_name_4?: string; + milkhouse?: string; + milkhouse_sqft?: string; + minor_civil_division_code?: string; + minor_civil_division_name?: string; + mobile_home_hookup?: string; + mortgage_amount?: string; + mortgage_amount_2?: string; + mortgage_due_date?: string; + mortgage_due_date_2?: string; + mortgage_interest_rate?: string; + mortgage_interest_rate_type?: string; + mortgage_lender_code?: string; + mortgage_rate_2?: string; + mortgage_recording_date?: string; + mortgage_recording_date_2?: string; + mortgage_term?: string; + mortgage_term_2?: string; + mortgage_term_type?: string; + mortgage_term_type_2?: string; + mortgage_type?: string; + mortgage_type_2?: string; + msa_code?: string; + msa_name?: string; + mud_room?: string; + multi_parcel_flag?: string; + name_title_company?: string; + neighborhood_code?: string; + number_of_buildings?: string; + office?: string; + office_sqft?: string; + other_tax_exemption?: string; + outdoor_kitchen_fireplace?: string; + overhead_door?: string; + owner_full_name?: string; + owner_full_name_2?: string; + owner_full_name_3?: string; + owner_full_name_4?: string; + owner_occupancy_status?: string; + ownership_transfer_date?: string; + ownership_transfer_doc_number?: string; + ownership_transfer_transaction_id?: string; + ownership_type?: string; + ownership_type_2?: string; + ownership_vesting_relation_code?: string; + parcel_account_number?: string; + parcel_map_book?: string; + parcel_map_page?: string; + parcel_number_alternate?: string; + parcel_number_formatted?: string; + parcel_number_previous?: string; + parcel_number_year_added?: string; + parcel_number_year_change?: string; + parcel_raw_number?: string; + parcel_shell_record?: string; + parking_spaces?: string; + patio_area?: string; + phase_name?: string; + plumbing_fixtures_count?: string; + pole_struct?: string; + pole_struct_sqft?: string; + pond?: string; + pool?: string; + pool_area?: string; + poolhouse?: string; + poolhouse_sqft?: string; + porch?: string; + porch_area?: string; + poultry_house?: string; + poultry_house_sqft?: string; + previous_assessed_value?: string; + prior_sale_amount?: string; + prior_sale_date?: string; + property_address_carrier_route_code?: string; + property_address_city?: string; + property_address_full?: string; + property_address_house_number?: string; + property_address_post_direction?: string; + property_address_pre_direction?: string; + property_address_state?: string; + property_address_street_name?: string; + property_address_street_suffix?: string; + property_address_unit_designator?: string; + property_address_unit_value?: string; + property_address_zip_4?: string; + property_address_zipcode?: string; + publication_date?: string; + quarter?: string; + quarter_quarter?: string; + quonset?: string; + quonset_sqft?: string; + range?: string; + recording_date?: string; + roof_cover?: string; + roof_frame?: string; + rooms?: string; + rv_parking?: string; + safe_room?: string; + sale_amount?: string; + sale_date?: string; + sauna?: string; + section?: string; + security_alarm?: string; + senior_tax_exemption?: string; + sewer_type?: string; + shed?: string; + shed_sqft?: string; + silo?: string; + silo_sqft?: string; + sitting_room?: string; + situs_county?: string; + situs_state?: string; + sound_system?: string; + sports_court?: string; + sprinklers?: string; + stable?: string; + stable_sqft?: string; + storage_building?: string; + storage_buildling_sqft?: string; + stories_number?: string; + storm_shelter?: string; + storm_shutter?: string; + structure_style?: string; + study?: string; + subdivision?: string; + suffix?: string; + suffix_2?: string; + suffix_3?: string; + suffix_4?: string; + sunroom?: string; + tax_assess_year?: string; + tax_billed_amount?: string; + tax_delinquent_year?: string; + tax_fiscal_year?: string; + tax_jurisdiction?: string; + tax_rate_area?: string; + tennis_court?: string; + topography_code?: string; + total_market_value?: string; + township?: string; + tract_number?: string; + transfer_amount?: string; + trust_description?: string; + unit_count?: string; + upper_floors_sqft?: string; + utility?: string; + utility_building?: string; + utility_building_sqft?: string; + utility_sqft?: string; + veteran_tax_exemption?: string; + view_description?: string; + water_feature?: string; + water_service_type?: string; + wet_bar?: string; + widow_tax_exemption?: string; + width_linear_footage?: string; + wine_cellar?: string; + financial_history?: RawFinancialHistory[]; + year_built?: string; + zoning?: string; +} + +interface RawEnrichmentResponse { + smarty_key?: string; + data_set_name?: string; + data_subset_name?: string; + attributes?: RawEnrichmentAttributes; +} + +export interface FinancialAttributes { + assessedImprovementPercent: string | undefined; + assessedImprovementValue: string | undefined; + assessedLandValue: string | undefined; + assessedValue: string | undefined; + assessorLastUpdate: string | undefined; + assessorTaxrollUpdate: string | undefined; + contactCity: string | undefined; + contactCrrt: string | undefined; + contactFullAddress: string | undefined; + contactHouseNumber: string | undefined; + contactMailInfoFormat: string | undefined; + contactMailInfoPrivacy: string | undefined; + contactMailingCounty: string | undefined; + contactMailingFips: string | undefined; + contactPostDirection: string | undefined; + contactPreDirection: string | undefined; + contactState: string | undefined; + contactStreetName: string | undefined; + contactSuffix: string | undefined; + contactUnitDesignator: string | undefined; + contactValue: string | undefined; + contactZip: string | undefined; + contactZip4: string | undefined; + deedDocumentPage: string | undefined; + deedDocumentBook: string | undefined; + deedDocumentNumber: string | undefined; + deedOwnerFirstName: string | undefined; + deedOwnerFirstName2: string | undefined; + deedOwnerFirstName3: string | undefined; + deedOwnerFirstName4: string | undefined; + deedOwnerFullName: string | undefined; + deedOwnerFullName2: string | undefined; + deedOwnerFullName3: string | undefined; + deedOwnerFullName4: string | undefined; + deedOwnerLastName: string | undefined; + deedOwnerLastName2: string | undefined; + deedOwnerLastName3: string | undefined; + deedOwnerLastName4: string | undefined; + deedOwnerMiddleName: string | undefined; + deedOwnerMiddleName2: string | undefined; + deedOwnerMiddleName3: string | undefined; + deedOwnerMiddleName4: string | undefined; + deedOwnerSuffix: string | undefined; + deedOwnerSuffix2: string | undefined; + deedOwnerSuffix3: string | undefined; + deedOwnerSuffix4: string | undefined; + deedSaleDate: string | undefined; + deedSalePrice: string | undefined; + deedTransactionId: string | undefined; + disabledTaxExemption: string | undefined; + homeownerTaxExemption: string | undefined; + marketImprovementPercent: string | undefined; + marketImprovementValue: string | undefined; + marketLandValue: string | undefined; + marketValueYear: string | undefined; + matchType: string | undefined; + otherTaxExemption: string | undefined; + ownershipTransferDate: string | undefined; + ownershipTransferDocNumber: string | undefined; + ownershipTransferTransactionId: string | undefined; + ownershipType: string | undefined; + ownershipType2: string | undefined; + previousAssessedValue: string | undefined; + priorSaleAmount: string | undefined; + priorSaleDate: string | undefined; + saleAmount: string | undefined; + saleDate: string | undefined; + seniorTaxExemption: string | undefined; + taxAssessYear: string | undefined; + taxBilledAmount: string | undefined; + taxDelinquentYear: string | undefined; + taxFiscalYear: string | undefined; + taxRateArea: string | undefined; + totalMarketValue: string | undefined; + trustDescription: string | undefined; + veteranTaxExemption: string | undefined; + widowTaxExemption: string | undefined; + financialHistory: FinancialHistory[]; +} + +interface RawFinancialAttributes { + assessed_improvement_percent?: string; + assessed_improvement_value?: string; + assessed_land_value?: string; + assessed_value?: string; + assessor_last_update?: string; + assessor_taxroll_update?: string; + contact_city?: string; + contact_crrt?: string; + contact_full_address?: string; + contact_house_number?: string; + contact_main_info_format?: string; + contact_mail_info_privacy?: string; + contact_mailing_county?: string; + contact_mailing_fips?: string; + contact_post_direction?: string; + contact_pre_direction?: string; + contact_state?: string; + contact_street_name?: string; + contact_suffix?: string; + contact_unit_designator?: string; + contact_value?: string; + contact_zip?: string; + contact_zip4?: string; + deed_document_page?: string; + deed_document_book?: string; + deed_document_number?: string; + deed_owner_first_name?: string; + deed_owner_first_name2?: string; + deed_owner_first_name3?: string; + deed_owner_first_name4?: string; + deed_owner_full_name?: string; + deed_owner_full_name2?: string; + deed_owner_full_name3?: string; + deed_owner_full_name4?: string; + deed_owner_last_name?: string; + deed_owner_last_name2?: string; + deed_owner_last_name3?: string; + deed_owner_last_name4?: string; + deed_owner_middle_name?: string; + deed_owner_middle_name2?: string; + deed_owner_middle_name3?: string; + deed_owner_middle_name4?: string; + deed_owner_suffix?: string; + deed_owner_suffix2?: string; + deed_owner_suffix3?: string; + deed_owner_suffix4?: string; + deed_sale_date?: string; + deed_sale_price?: string; + deed_transaction_id?: string; + disabled_tax_exemption?: string; + homeowner_tax_exemption?: string; + market_improvement_percent?: string; + market_improvement_value?: string; + market_land_value?: string; + market_value_year?: string; + match_type?: string; + other_tax_exemption?: string; + ownership_transfer_date?: string; + ownership_transfer_doc_number?: string; + ownership_transfer_transaction_id?: string; + ownership_type?: string; + ownership_type_2?: string; + previous_assessed_value?: string; + prior_sale_amount?: string; + prior_sale_date?: string; + sale_amount?: string; + sale_date?: string; + senior_tax_exemption?: string; + tax_assess_year?: string; + tax_billed_amount?: string; + tax_delinquent_year?: string; + tax_fiscal_year?: string; + tax_rate_area?: string; + total_market_value?: string; + trust_description?: string; + veteran_tax_exemption?: string; + widow_tax_exemption?: string; + financial_history?: RawFinancialHistory[]; +} + +interface RawFinancialResponse { + smarty_key?: string; + data_set_name?: string; + data_subset_name?: string; + attributes?: RawFinancialAttributes; +} + +export interface GeoCensusBlock { + accuracy: string | undefined; + geoid: string | undefined; +} + +export interface GeoCensusCountyDivision { + accuracy: string | undefined; + code: string | undefined; + name: string | undefined; +} + +export interface GeoCensusTract { + code: string | undefined; +} + +export interface GeoCoreBasedStatArea { + code: string | undefined; + name: string | undefined; +} + +export interface GeoPlace { + accuracy: string | undefined; + code: string | undefined; + name: string | undefined; + type: string | undefined; +} + +export interface GeoAttributes { + censusBlock: GeoCensusBlock; + censusCountyDivision: GeoCensusCountyDivision; + censusTract: GeoCensusTract; + coreBasedStatArea: GeoCoreBasedStatArea; + place: GeoPlace; +} + +interface RawGeoCensusBlock { + accuracy?: string; + geoid?: string; +} + +interface RawGeoCensusCountyDivision { + accuracy?: string; + code?: string; + name?: string; +} + +interface RawGeoCensusTract { + code?: string; +} + +interface RawGeoCoreBasedStatArea { + code?: string; + name?: string; +} + +interface RawGeoPlace { + accuracy?: string; + code?: string; + name?: string; + type?: string; +} + +interface RawGeoAttributes { + census_block?: RawGeoCensusBlock; + census_county_division?: RawGeoCensusCountyDivision; + census_tract?: RawGeoCensusTract; + core_based_stat_area?: RawGeoCoreBasedStatArea; + place?: RawGeoPlace; +} + +interface RawGeoResponse { + smarty_key?: string; + data_set_name?: string; + attributes?: RawGeoAttributes; +} + +export class Response { + smartyKey: string; + dataSetName: string; + dataSubsetName: string; + attributes: EnrichmentAttributes; + + constructor(responseData: RawEnrichmentResponse) { + this.smartyKey = responseData.smarty_key ?? ""; + this.dataSetName = responseData.data_set_name ?? ""; + this.dataSubsetName = responseData.data_subset_name ?? ""; + + this.attributes = {} as EnrichmentAttributes; + if (responseData.attributes) { + this.attributes.firstFloorSqft = responseData.attributes["1st_floor_sqft"]; + this.attributes.secondFloorSqft = responseData.attributes["2nd_floor_sqft"]; + this.attributes.acres = responseData.attributes.acres; + this.attributes.addressInfoPrivacy = responseData.attributes.address_info_privacy; + this.attributes.airConditioner = responseData.attributes.air_conditioner; + this.attributes.arborPergola = responseData.attributes.arbor_pergola; + this.attributes.assessedImprovementPercent = + responseData.attributes.assessed_improvement_percent; + this.attributes.assessedImprovementValue = responseData.attributes.assessed_improvement_value; + this.attributes.assessedLandValue = responseData.attributes.assessed_land_value; + this.attributes.assessedValue = responseData.attributes.assessed_value; + this.attributes.assessorLastUpdate = responseData.attributes.assessor_last_update; + this.attributes.assessorTaxrollUpdate = responseData.attributes.assessor_taxroll_update; + this.attributes.atticArea = responseData.attributes.attic_area; + this.attributes.atticFlag = responseData.attributes.attic_flag; + this.attributes.balcony = responseData.attributes.balcony; + this.attributes.balconyArea = responseData.attributes.balcony_area; + this.attributes.basementSqft = responseData.attributes.basement_sqft; + this.attributes.basementSqftFinished = responseData.attributes.basement_sqft_finished; + this.attributes.basementsqftUnfinished = responseData.attributes.basement_sqft_unfinished; + this.attributes.bathHouse = responseData.attributes.bath_house; + this.attributes.bathHouseSqft = responseData.attributes.bath_house_sqft; + this.attributes.bathroomsPartial = responseData.attributes.bathrooms_partial; + this.attributes.bathroomsTotal = responseData.attributes.bathrooms_total; + this.attributes.bedrooms = responseData.attributes.bedrooms; + this.attributes.block1 = responseData.attributes.block_1; + this.attributes.block2 = responseData.attributes.block_2; + this.attributes.boatAccess = responseData.attributes.boat_access; + this.attributes.boatHouse = responseData.attributes.boat_house; + this.attributes.boatHouseSqft = responseData.attributes.boat_house_sqft; + this.attributes.boatLift = responseData.attributes.boat_lift; + this.attributes.bonusRoom = responseData.attributes.bonus_room; + this.attributes.breakfastNook = responseData.attributes.breakfast_nook; + this.attributes.breezeway = responseData.attributes.breezeway; + this.attributes.buildingDefinitionCode = responseData.attributes.building_definition; + this.attributes.buildingSqft = responseData.attributes.building_sqft; + this.attributes.cabin = responseData.attributes.cabin; + this.attributes.cabinSqft = responseData.attributes.cabin_sqft; + this.attributes.canopy = responseData.attributes.canopy; + this.attributes.canopySqft = responseData.attributes.canopy_sqft; + this.attributes.carport = responseData.attributes.carport; + this.attributes.carportSqft = responseData.attributes.carport_sqft; + this.attributes.cbsaCode = responseData.attributes.cbsa_code; + this.attributes.cbsaName = responseData.attributes.cbsa_name; + this.attributes.cellar = responseData.attributes.cellar; + this.attributes.censusBlock = responseData.attributes.census_block; + this.attributes.censusTract = responseData.attributes.census_tract; + this.attributes.censusBlockGroup = responseData.attributes.census_block_group; + this.attributes.censusFipsPlaceCode = responseData.attributes.census_fips_place_code; + this.attributes.centralVacuum = responseData.attributes.central_vacuum; + this.attributes.codeTitleCompany = responseData.attributes.code_title_company; + this.attributes.combinedStatisticalArea = responseData.attributes.combined_statistical_area; + this.attributes.communityRec = responseData.attributes.community_rec; + this.attributes.companyFlag = responseData.attributes.company_flag; + this.attributes.congressionalDistrict = responseData.attributes.congressional_district; + this.attributes.constructionType = responseData.attributes.construction_type; + this.attributes.contactCity = responseData.attributes.contact_city; + this.attributes.contactCrrt = responseData.attributes.contact_crrt; + this.attributes.contactFullAddress = responseData.attributes.contact_full_address; + this.attributes.contactHouseNumber = responseData.attributes.contact_house_number; + this.attributes.contactMailInfoFormat = responseData.attributes.contact_main_info_format; + this.attributes.contactMailInfoPrivacy = responseData.attributes.contact_mail_info_privacy; + this.attributes.contactMailingCounty = responseData.attributes.contact_mailing_county; + this.attributes.contactMailingFips = responseData.attributes.contact_mailing_fips; + this.attributes.contactPostDirection = responseData.attributes.contact_post_direction; + this.attributes.contactPreDirection = responseData.attributes.contact_pre_direction; + this.attributes.contactState = responseData.attributes.contact_state; + this.attributes.contactStreetName = responseData.attributes.contact_street_name; + this.attributes.contactSuffix = responseData.attributes.contact_suffix; + this.attributes.contactUnitDesignator = responseData.attributes.contact_unit_designator; + this.attributes.contactValue = responseData.attributes.contact_value; + this.attributes.contactZip = responseData.attributes.contact_zip; + this.attributes.contactZip4 = responseData.attributes.contact_zip4; + this.attributes.courtyard = responseData.attributes.courtyard; + this.attributes.courtyardArea = responseData.attributes.courtyard_area; + this.attributes.deck = responseData.attributes.deck; + this.attributes.deckArea = responseData.attributes.deck_area; + this.attributes.deedDocumentPage = responseData.attributes.deed_document_page; + this.attributes.deedDocumentBook = responseData.attributes.deed_document_book; + this.attributes.deedDocumentNumber = responseData.attributes.deed_document_number; + this.attributes.deedOwnerFirstName = responseData.attributes.deed_owner_first_name; + this.attributes.deedOwnerFirstName2 = responseData.attributes.deed_owner_first_name2; + this.attributes.deedOwnerFirstName3 = responseData.attributes.deed_owner_first_name3; + this.attributes.deedOwnerFirstName4 = responseData.attributes.deed_owner_first_name4; + this.attributes.deedOwnerFullName = responseData.attributes.deed_owner_full_name; + this.attributes.deedOwnerFullName2 = responseData.attributes.deed_owner_full_name2; + this.attributes.deedOwnerFullName3 = responseData.attributes.deed_owner_full_name3; + this.attributes.deedOwnerFullName4 = responseData.attributes.deed_owner_full_name4; + this.attributes.deedOwnerLastName = responseData.attributes.deed_owner_last_name; + this.attributes.deedOwnerLastName2 = responseData.attributes.deed_owner_last_name2; + this.attributes.deedOwnerLastName3 = responseData.attributes.deed_owner_last_name3; + this.attributes.deedOwnerLastName4 = responseData.attributes.deed_owner_last_name4; + this.attributes.deedOwnerMiddleName = responseData.attributes.deed_owner_middle_name; + this.attributes.deedOwnerMiddleName2 = responseData.attributes.deed_owner_middle_name2; + this.attributes.deedOwnerMiddleName3 = responseData.attributes.deed_owner_middle_name3; + this.attributes.deedOwnerMiddleName4 = responseData.attributes.deed_owner_middle_name4; + this.attributes.deedOwnerSuffix = responseData.attributes.deed_owner_suffix; + this.attributes.deedOwnerSuffix2 = responseData.attributes.deed_owner_suffix2; + this.attributes.deedOwnerSuffix3 = responseData.attributes.deed_owner_suffix3; + this.attributes.deedOwnerSuffix4 = responseData.attributes.deed_owner_suffix4; + this.attributes.deedSaleDate = responseData.attributes.deed_sale_date; + this.attributes.deedSalePrice = responseData.attributes.deed_sale_price; + this.attributes.deedTransactionId = responseData.attributes.deed_transaction_id; + this.attributes.depthLinearFootage = responseData.attributes.depth_linear_footage; + this.attributes.disabledTaxExemption = responseData.attributes.disabled_tax_exemption; + this.attributes.drivewaySqft = responseData.attributes.driveway_sqft; + this.attributes.drivewayType = responseData.attributes.driveway_type; + this.attributes.effectiveYearBuilt = responseData.attributes.effective_year_built; + this.attributes.elevationFeet = responseData.attributes.elevation_feet; + this.attributes.elevator = responseData.attributes.elevator; + this.attributes.equestrianArena = responseData.attributes.equestrian_arena; + this.attributes.escalator = responseData.attributes.escalator; + this.attributes.exerciseRoom = responseData.attributes.exercise_room; + this.attributes.exteriorWalls = responseData.attributes.exterior_walls; + this.attributes.familyRoom = responseData.attributes.family_room; + this.attributes.financialHistory = !responseData.attributes.financial_history + ? [] + : responseData.attributes.financial_history.map((history): FinancialHistory => { + return { + codeTitleCompany: history.code_title_company, + instrumentDate: history.instrument_date, + interestRateType2: history.interest_rate_type_2, + lenderAddress: history.lender_address, + lenderAddress2: history.lender_address_2, + lenderCity: history.lender_city, + lenderCity2: history.lender_city_2, + lenderCode: history.lender_code, + lenderCode2: history.lender_code_2, + lenderFirstName: history.lender_first_name, + lenderFirstName2: history.lender_first_name_2, + lenderLastName: history.lender_last_name, + lenderLastName2: history.lender_last_name_2, + lenderName: history.lender_name, + lenderName2: history.lender_name_2, + lenderSellerCarryBack: history.lender_seller_carry_back, + lenderSellerCarryBack2: history.lender_seller_carry_back_2, + lenderState: history.lender_state, + lenderState2: history.lender_state_2, + lenderZip: history.lender_zip, + lenderZip2: history.lender_zip_2, + lenderZipExtended: history.lender_zip_extended, + lenderZipExtended2: history.lender_zip_extended_2, + mortgageAmount: history.mortgage_amount, + mortgageAmount2: history.mortgage_amount_2, + mortgageDueDate: history.mortgage_due_date, + mortgageDueDate2: history.mortgage_due_date_2, + mortgageInterestRate: history.mortgage_interest_rate, + mortgageInterestRateType: history.mortgage_interest_rate_type, + mortgageLenderCode: history.mortgage_lender_code, + mortgageRate: history.mortgage_rate, + mortgageRate2: history.mortgage_rate_2, + mortgageRecordingDate: history.mortgage_recording_date, + mortgageRecordingDate2: history.mortgage_recording_date_2, + mortgageTerm: history.mortgage_term, + mortgageTerm2: history.mortgage_term_2, + mortgageTermType: history.mortgage_term_type, + mortgageTermType2: history.mortgage_term_type_2, + mortgageType: history.mortgage_type, + mortgageType2: history.mortgage_type_2, + multiParcelFlag: history.multi_parcel_flag, + nameTitleCompany: history.name_title_company, + recordingDate: history.recording_date, + transferAmount: history.transfer_amount, + }; + }); + this.attributes.fence = responseData.attributes.fence; + this.attributes.fenceArea = responseData.attributes.fence_area; + this.attributes.fipsCode = responseData.attributes.fips_code; + this.attributes.fireResistanceCode = responseData.attributes.fire_resistance_code; + this.attributes.fireSprinklersFlag = responseData.attributes.fire_sprinkler_flag; + this.attributes.fireplace = responseData.attributes.fireplace; + this.attributes.fireplaceNumber = responseData.attributes.fireplace_number; + this.attributes.firstName = responseData.attributes.first_name; + this.attributes.firstName2 = responseData.attributes.first_name2; + this.attributes.firstName3 = responseData.attributes.first_name3; + this.attributes.firstName4 = responseData.attributes.first_name4; + this.attributes.flooring = responseData.attributes.flooring; + this.attributes.foundation = responseData.attributes.foundation; + this.attributes.gameRoom = responseData.attributes.game_room; + this.attributes.garage = responseData.attributes.garage; + this.attributes.garageSqft = responseData.attributes.garage_sqft; + this.attributes.gazebo = responseData.attributes.gazebo; + this.attributes.gazeboSqft = responseData.attributes.gazebo_sqft; + this.attributes.golfCourse = responseData.attributes.golf_course; + this.attributes.grainery = responseData.attributes.grainery; + this.attributes.grainerySqft = responseData.attributes.grainery_sqft; + this.attributes.greatRoom = responseData.attributes.great_room; + this.attributes.greenhouse = responseData.attributes.greenhouse; + this.attributes.greenhouseSqft = responseData.attributes.greenhouse_sqft; + this.attributes.grossSqft = responseData.attributes.gross_sqft; + this.attributes.guesthouse = responseData.attributes.guesthouse; + this.attributes.guesthouseSqft = responseData.attributes.guesthouse_sqft; + this.attributes.handicapAccessibility = responseData.attributes.handicap_accessibility; + this.attributes.heat = responseData.attributes.heat; + this.attributes.heatFuelType = responseData.attributes.heat_fuel_type; + this.attributes.hobbyRoom = responseData.attributes.hobby_room; + this.attributes.homeownerTaxExemption = responseData.attributes.homeowner_tax_exemption; + this.attributes.instrumentDate = responseData.attributes.instrument_date; + this.attributes.intercomSystem = responseData.attributes.intercom_system; + this.attributes.interestRateType2 = responseData.attributes.interest_rate_type_2; + this.attributes.interiorStructure = responseData.attributes.interior_structure; + this.attributes.kennel = responseData.attributes.kennel; + this.attributes.kennelSqft = responseData.attributes.kennel_sqft; + this.attributes.landUseCode = responseData.attributes.land_use_code; + this.attributes.landUseGroup = responseData.attributes.land_use_group; + this.attributes.landUseStandard = responseData.attributes.land_use_standard; + this.attributes.lastName = responseData.attributes.last_name; + this.attributes.lastName2 = responseData.attributes.last_name_2; + this.attributes.lastName3 = responseData.attributes.last_name_3; + this.attributes.lastName4 = responseData.attributes.last_name_4; + this.attributes.latitude = responseData.attributes.latitude; + this.attributes.laundry = responseData.attributes.laundry; + this.attributes.leanTo = responseData.attributes.lean_to; + this.attributes.leanToSqft = responseData.attributes.lean_to_sqft; + this.attributes.legalDescription = responseData.attributes.legal_description; + this.attributes.legalUnit = responseData.attributes.legal_unit; + this.attributes.lenderAddress = responseData.attributes.lender_address; + this.attributes.lenderAddress2 = responseData.attributes.lender_address_2; + this.attributes.lenderCity = responseData.attributes.lender_city; + this.attributes.lenderCity2 = responseData.attributes.lender_city_2; + this.attributes.lenderCode = responseData.attributes.lender_code; + this.attributes.lenderCode2 = responseData.attributes.lender_code_2; + this.attributes.lenderFirstName = responseData.attributes.lender_first_name; + this.attributes.lenderFirstName2 = responseData.attributes.lender_first_name_2; + this.attributes.lenderLastName = responseData.attributes.lender_last_name; + this.attributes.lenderLastName2 = responseData.attributes.lender_last_name_2; + this.attributes.lenderName = responseData.attributes.lender_name; + this.attributes.lenderName2 = responseData.attributes.lender_name_2; + this.attributes.lenderSellerCarryBack = responseData.attributes.lender_seller_carry_back; + this.attributes.lenderSellerCarryBack2 = responseData.attributes.lender_seller_carry_back_2; + this.attributes.lenderState = responseData.attributes.lender_state; + this.attributes.lenderState2 = responseData.attributes.lender_state_2; + this.attributes.lenderZip = responseData.attributes.lender_zip; + this.attributes.lenderZip2 = responseData.attributes.lender_zip_2; + this.attributes.lenderZipExtended = responseData.attributes.lender_zip_extended; + this.attributes.lenderZipExtended2 = responseData.attributes.lender_zip_extended_2; + this.attributes.loadingPlatform = responseData.attributes.loading_platform; + this.attributes.loadingPlatformSqft = responseData.attributes.loading_platform_sqft; + this.attributes.longitude = responseData.attributes.longitude; + this.attributes.lot1 = responseData.attributes.lot_1; + this.attributes.lot2 = responseData.attributes.lot_2; + this.attributes.lot3 = responseData.attributes.lot_3; + this.attributes.lotSqft = responseData.attributes.lot_sqft; + this.attributes.marketImprovementPercent = responseData.attributes.market_improvement_percent; + this.attributes.marketImprovementValue = responseData.attributes.market_improvement_value; + this.attributes.marketLandValue = responseData.attributes.market_land_value; + this.attributes.marketValueYear = responseData.attributes.market_value_year; + this.attributes.matchType = responseData.attributes.match_type; + this.attributes.mediaRoom = responseData.attributes.media_room; + this.attributes.metroDivision = responseData.attributes.metro_division; + this.attributes.middleName = responseData.attributes.middle_name; + this.attributes.middleName2 = responseData.attributes.middle_name_2; + this.attributes.middleName3 = responseData.attributes.middle_name_3; + this.attributes.middleName4 = responseData.attributes.middle_name_4; + this.attributes.milkhouse = responseData.attributes.milkhouse; + this.attributes.milkhouseSqft = responseData.attributes.milkhouse_sqft; + this.attributes.minorCivilDivisionCode = responseData.attributes.minor_civil_division_code; + this.attributes.minorCivilDivisionName = responseData.attributes.minor_civil_division_name; + this.attributes.mobileHomeHookup = responseData.attributes.mobile_home_hookup; + this.attributes.mortgageAmount = responseData.attributes.mortgage_amount; + this.attributes.mortgageAmount2 = responseData.attributes.mortgage_amount_2; + this.attributes.mortgageDueDate = responseData.attributes.mortgage_due_date; + this.attributes.mortgageDueDate2 = responseData.attributes.mortgage_due_date_2; + this.attributes.mortgageInterestRate = responseData.attributes.mortgage_interest_rate; + this.attributes.mortgageInterestRateType = + responseData.attributes.mortgage_interest_rate_type; + this.attributes.mortgageLenderCode = responseData.attributes.mortgage_lender_code; + this.attributes.mortgageRate2 = responseData.attributes.mortgage_rate_2; + this.attributes.mortgageRecordingDate = responseData.attributes.mortgage_recording_date; + this.attributes.mortgageRecordingDate2 = responseData.attributes.mortgage_recording_date_2; + this.attributes.mortgageTerm = responseData.attributes.mortgage_term; + this.attributes.mortgageTerm2 = responseData.attributes.mortgage_term_2; + this.attributes.mortgageTermType = responseData.attributes.mortgage_term_type; + this.attributes.mortgageTermType2 = responseData.attributes.mortgage_term_type_2; + this.attributes.mortgageType = responseData.attributes.mortgage_type; + this.attributes.mortgageType2 = responseData.attributes.mortgage_type_2; + this.attributes.msaCode = responseData.attributes.msa_code; + this.attributes.msaName = responseData.attributes.msa_name; + this.attributes.mudRoom = responseData.attributes.mud_room; + this.attributes.multiParcelFlag = responseData.attributes.multi_parcel_flag; + this.attributes.nameTitleCompany = responseData.attributes.name_title_company; + this.attributes.neighborhoodCode = responseData.attributes.neighborhood_code; + this.attributes.numberOfBuildings = responseData.attributes.number_of_buildings; + this.attributes.office = responseData.attributes.office; + this.attributes.officeSqft = responseData.attributes.office_sqft; + this.attributes.otherTaxExemption = responseData.attributes.other_tax_exemption; + this.attributes.outdoorKitchenFireplace = responseData.attributes.outdoor_kitchen_fireplace; + this.attributes.overheadDoor = responseData.attributes.overhead_door; + this.attributes.ownerFullName = responseData.attributes.owner_full_name; + this.attributes.ownerFullName2 = responseData.attributes.owner_full_name_2; + this.attributes.ownerFullName3 = responseData.attributes.owner_full_name_3; + this.attributes.ownerFullName4 = responseData.attributes.owner_full_name_4; + this.attributes.ownerOccupancyStatus = responseData.attributes.owner_occupancy_status; + this.attributes.ownershipTransferDate = responseData.attributes.ownership_transfer_date; + this.attributes.ownershipTransferDocNumber = + responseData.attributes.ownership_transfer_doc_number; + this.attributes.ownershipTransferTransactionId = + responseData.attributes.ownership_transfer_transaction_id; + this.attributes.ownershipType = responseData.attributes.ownership_type; + this.attributes.ownershipType2 = responseData.attributes.ownership_type_2; + this.attributes.ownershipVestingRelationCode = + responseData.attributes.ownership_vesting_relation_code; + this.attributes.parcelAccountNumber = responseData.attributes.parcel_account_number; + this.attributes.parcelMapBook = responseData.attributes.parcel_map_book; + this.attributes.parcelMapPage = responseData.attributes.parcel_map_page; + this.attributes.parcelNumberAlternate = responseData.attributes.parcel_number_alternate; + this.attributes.parcelNumberFormatted = responseData.attributes.parcel_number_formatted; + this.attributes.parcelNumberPrevious = responseData.attributes.parcel_number_previous; + this.attributes.parcelNumberYearAdded = responseData.attributes.parcel_number_year_added; + this.attributes.parcelNumberYearChange = responseData.attributes.parcel_number_year_change; + this.attributes.parcelRawNumber = responseData.attributes.parcel_raw_number; + this.attributes.parcelShellRecord = responseData.attributes.parcel_shell_record; + this.attributes.parkingSpaces = responseData.attributes.parking_spaces; + this.attributes.patioArea = responseData.attributes.patio_area; + this.attributes.phaseName = responseData.attributes.phase_name; + this.attributes.plumbingFixturesCount = responseData.attributes.plumbing_fixtures_count; + this.attributes.poleStruct = responseData.attributes.pole_struct; + this.attributes.poleStructSqft = responseData.attributes.pole_struct_sqft; + this.attributes.pond = responseData.attributes.pond; + this.attributes.pool = responseData.attributes.pool; + this.attributes.poolArea = responseData.attributes.pool_area; + this.attributes.poolhouse = responseData.attributes.poolhouse; + this.attributes.poolhouseSqft = responseData.attributes.poolhouse_sqft; + this.attributes.porch = responseData.attributes.porch; + this.attributes.porchArea = responseData.attributes.porch_area; + this.attributes.poultryHouse = responseData.attributes.poultry_house; + this.attributes.poultryHouseSqft = responseData.attributes.poultry_house_sqft; + this.attributes.previousAssessedValue = responseData.attributes.previous_assessed_value; + this.attributes.priorSaleAmount = responseData.attributes.prior_sale_amount; + this.attributes.priorSaleDate = responseData.attributes.prior_sale_date; + this.attributes.propertyAddressCarrierRouteCode = + responseData.attributes.property_address_carrier_route_code; + this.attributes.propertyAddressCity = responseData.attributes.property_address_city; + this.attributes.propertyAddressFull = responseData.attributes.property_address_full; + this.attributes.propertyAddressHouseNumber = + responseData.attributes.property_address_house_number; + this.attributes.propertyAddressPostDirection = + responseData.attributes.property_address_post_direction; + this.attributes.propertyAddressPreDirection = + responseData.attributes.property_address_pre_direction; + this.attributes.propertyAddressState = responseData.attributes.property_address_state; + this.attributes.propertyAddressStreetName = + responseData.attributes.property_address_street_name; + this.attributes.propertyAddressStreetSuffix = + responseData.attributes.property_address_street_suffix; + this.attributes.propertyAddressUnitDesignator = + responseData.attributes.property_address_unit_designator; + this.attributes.propertyAddressUnitValue = + responseData.attributes.property_address_unit_value; + this.attributes.propertyAddressZip4 = responseData.attributes.property_address_zip_4; + this.attributes.propertyAddressZipcode = responseData.attributes.property_address_zipcode; + this.attributes.publicationDate = responseData.attributes.publication_date; + this.attributes.quarter = responseData.attributes.quarter; + this.attributes.quarterQuarter = responseData.attributes.quarter_quarter; + this.attributes.quonset = responseData.attributes.quonset; + this.attributes.quonsetSqft = responseData.attributes.quonset_sqft; + this.attributes.range = responseData.attributes.range; + this.attributes.recordingDate = responseData.attributes.recording_date; + this.attributes.roofCover = responseData.attributes.roof_cover; + this.attributes.roofFrame = responseData.attributes.roof_frame; + this.attributes.rooms = responseData.attributes.rooms; + this.attributes.rvParking = responseData.attributes.rv_parking; + this.attributes.safeRoom = responseData.attributes.safe_room; + this.attributes.saleAmount = responseData.attributes.sale_amount; + this.attributes.saleDate = responseData.attributes.sale_date; + this.attributes.sauna = responseData.attributes.sauna; + this.attributes.section = responseData.attributes.section; + this.attributes.securityAlarm = responseData.attributes.security_alarm; + this.attributes.seniorTaxExemption = responseData.attributes.senior_tax_exemption; + this.attributes.sewerType = responseData.attributes.sewer_type; + this.attributes.shed = responseData.attributes.shed; + this.attributes.shedSqft = responseData.attributes.shed_sqft; + this.attributes.silo = responseData.attributes.silo; + this.attributes.siloSqft = responseData.attributes.silo_sqft; + this.attributes.sittingRoom = responseData.attributes.sitting_room; + this.attributes.situsCounty = responseData.attributes.situs_county; + this.attributes.situsState = responseData.attributes.situs_state; + this.attributes.soundSystem = responseData.attributes.sound_system; + this.attributes.sportsCourt = responseData.attributes.sports_court; + this.attributes.sprinklers = responseData.attributes.sprinklers; + this.attributes.stable = responseData.attributes.stable; + this.attributes.stableSqft = responseData.attributes.stable_sqft; + this.attributes.storageBuilding = responseData.attributes.storage_building; + this.attributes.storageBuildingSqft = responseData.attributes.storage_buildling_sqft; + this.attributes.storiesNumber = responseData.attributes.stories_number; + this.attributes.stormShelter = responseData.attributes.storm_shelter; + this.attributes.stormShutter = responseData.attributes.storm_shutter; + this.attributes.structureStyle = responseData.attributes.structure_style; + this.attributes.study = responseData.attributes.study; + this.attributes.subdivision = responseData.attributes.subdivision; + this.attributes.suffix = responseData.attributes.suffix; + this.attributes.suffix2 = responseData.attributes.suffix_2; + this.attributes.suffix3 = responseData.attributes.suffix_3; + this.attributes.suffix4 = responseData.attributes.suffix_4; + this.attributes.sunroom = responseData.attributes.sunroom; + this.attributes.taxAssessYear = responseData.attributes.tax_assess_year; + this.attributes.taxBilledAmount = responseData.attributes.tax_billed_amount; + this.attributes.taxDelinquentYear = responseData.attributes.tax_delinquent_year; + this.attributes.taxFiscalYear = responseData.attributes.tax_fiscal_year; + this.attributes.taxJurisdiction = responseData.attributes.tax_jurisdiction; + this.attributes.taxRateArea = responseData.attributes.tax_rate_area; + this.attributes.tennisCourt = responseData.attributes.tennis_court; + this.attributes.topographyCode = responseData.attributes.topography_code; + this.attributes.totalMarketValue = responseData.attributes.total_market_value; + this.attributes.township = responseData.attributes.township; + this.attributes.tractNumber = responseData.attributes.tract_number; + this.attributes.transferAmount = responseData.attributes.transfer_amount; + this.attributes.trustDescription = responseData.attributes.trust_description; + this.attributes.unitCount = responseData.attributes.unit_count; + this.attributes.upperFloorsSqft = responseData.attributes.upper_floors_sqft; + this.attributes.utility = responseData.attributes.utility; + this.attributes.utilityBuilding = responseData.attributes.utility_building; + this.attributes.utilityBuildingSqft = responseData.attributes.utility_building_sqft; + this.attributes.utilitySqft = responseData.attributes.utility_sqft; + this.attributes.veteranTaxExemption = responseData.attributes.veteran_tax_exemption; + this.attributes.viewDescription = responseData.attributes.view_description; + this.attributes.waterFeature = responseData.attributes.water_feature; + this.attributes.waterServiceType = responseData.attributes.water_service_type; + this.attributes.wetBar = responseData.attributes.wet_bar; + this.attributes.widowTaxExemption = responseData.attributes.widow_tax_exemption; + this.attributes.widthLinearFootage = responseData.attributes.width_linear_footage; + this.attributes.wineCellar = responseData.attributes.wine_cellar; + this.attributes.yearBuilt = responseData.attributes.year_built; + this.attributes.zoning = responseData.attributes.zoning; + } + } +} + +export class FinancialResponse { + smartyKey: string; + dataSetName: string; + dataSubsetName: string; + attributes: FinancialAttributes; + + constructor(responseData: RawFinancialResponse) { + this.smartyKey = responseData.smarty_key ?? ""; + this.dataSetName = responseData.data_set_name ?? ""; + this.dataSubsetName = responseData.data_subset_name ?? ""; + + this.attributes = {} as FinancialAttributes; + if (responseData.attributes) { + this.attributes.assessedImprovementPercent = + responseData.attributes.assessed_improvement_percent; + this.attributes.assessedImprovementValue = responseData.attributes.assessed_improvement_value; + this.attributes.assessedLandValue = responseData.attributes.assessed_land_value; + this.attributes.assessedValue = responseData.attributes.assessed_value; + this.attributes.assessorLastUpdate = responseData.attributes.assessor_last_update; + this.attributes.assessorTaxrollUpdate = responseData.attributes.assessor_taxroll_update; + this.attributes.contactCity = responseData.attributes.contact_city; + this.attributes.contactCrrt = responseData.attributes.contact_crrt; + this.attributes.contactFullAddress = responseData.attributes.contact_full_address; + this.attributes.contactHouseNumber = responseData.attributes.contact_house_number; + this.attributes.contactMailInfoFormat = responseData.attributes.contact_main_info_format; + this.attributes.contactMailInfoPrivacy = responseData.attributes.contact_mail_info_privacy; + this.attributes.contactMailingCounty = responseData.attributes.contact_mailing_county; + this.attributes.contactMailingFips = responseData.attributes.contact_mailing_fips; + this.attributes.contactPostDirection = responseData.attributes.contact_post_direction; + this.attributes.contactPreDirection = responseData.attributes.contact_pre_direction; + this.attributes.contactState = responseData.attributes.contact_state; + this.attributes.contactStreetName = responseData.attributes.contact_street_name; + this.attributes.contactSuffix = responseData.attributes.contact_suffix; + this.attributes.contactUnitDesignator = responseData.attributes.contact_unit_designator; + this.attributes.contactValue = responseData.attributes.contact_value; + this.attributes.contactZip = responseData.attributes.contact_zip; + this.attributes.contactZip4 = responseData.attributes.contact_zip4; + this.attributes.deedDocumentPage = responseData.attributes.deed_document_page; + this.attributes.deedDocumentBook = responseData.attributes.deed_document_book; + this.attributes.deedDocumentNumber = responseData.attributes.deed_document_number; + this.attributes.deedOwnerFirstName = responseData.attributes.deed_owner_first_name; + this.attributes.deedOwnerFirstName2 = responseData.attributes.deed_owner_first_name2; + this.attributes.deedOwnerFirstName3 = responseData.attributes.deed_owner_first_name3; + this.attributes.deedOwnerFirstName4 = responseData.attributes.deed_owner_first_name4; + this.attributes.deedOwnerFullName = responseData.attributes.deed_owner_full_name; + this.attributes.deedOwnerFullName2 = responseData.attributes.deed_owner_full_name2; + this.attributes.deedOwnerFullName3 = responseData.attributes.deed_owner_full_name3; + this.attributes.deedOwnerFullName4 = responseData.attributes.deed_owner_full_name4; + this.attributes.deedOwnerLastName = responseData.attributes.deed_owner_last_name; + this.attributes.deedOwnerLastName2 = responseData.attributes.deed_owner_last_name2; + this.attributes.deedOwnerLastName3 = responseData.attributes.deed_owner_last_name3; + this.attributes.deedOwnerLastName4 = responseData.attributes.deed_owner_last_name4; + this.attributes.deedOwnerMiddleName = responseData.attributes.deed_owner_middle_name; + this.attributes.deedOwnerMiddleName2 = responseData.attributes.deed_owner_middle_name2; + this.attributes.deedOwnerMiddleName3 = responseData.attributes.deed_owner_middle_name3; + this.attributes.deedOwnerMiddleName4 = responseData.attributes.deed_owner_middle_name4; + this.attributes.deedOwnerSuffix = responseData.attributes.deed_owner_suffix; + this.attributes.deedOwnerSuffix2 = responseData.attributes.deed_owner_suffix2; + this.attributes.deedOwnerSuffix3 = responseData.attributes.deed_owner_suffix3; + this.attributes.deedOwnerSuffix4 = responseData.attributes.deed_owner_suffix4; + this.attributes.deedSaleDate = responseData.attributes.deed_sale_date; + this.attributes.deedSalePrice = responseData.attributes.deed_sale_price; + this.attributes.deedTransactionId = responseData.attributes.deed_transaction_id; + this.attributes.disabledTaxExemption = responseData.attributes.disabled_tax_exemption; + this.attributes.financialHistory = !responseData.attributes.financial_history + ? [] + : responseData.attributes.financial_history.map((history): FinancialHistory => { + return { + codeTitleCompany: history.code_title_company, + instrumentDate: history.instrument_date, + interestRateType2: history.interest_rate_type_2, + lenderAddress: history.lender_address, + lenderAddress2: history.lender_address_2, + lenderCity: history.lender_city, + lenderCity2: history.lender_city_2, + lenderCode: history.lender_code, + lenderCode2: history.lender_code_2, + lenderFirstName: history.lender_first_name, + lenderFirstName2: history.lender_first_name_2, + lenderLastName: history.lender_last_name, + lenderLastName2: history.lender_last_name_2, + lenderName: history.lender_name, + lenderName2: history.lender_name_2, + lenderSellerCarryBack: history.lender_seller_carry_back, + lenderSellerCarryBack2: history.lender_seller_carry_back_2, + lenderState: history.lender_state, + lenderState2: history.lender_state_2, + lenderZip: history.lender_zip, + lenderZip2: history.lender_zip_2, + lenderZipExtended: history.lender_zip_extended, + lenderZipExtended2: history.lender_zip_extended_2, + mortgageAmount: history.mortgage_amount, + mortgageAmount2: history.mortgage_amount_2, + mortgageDueDate: history.mortgage_due_date, + mortgageDueDate2: history.mortgage_due_date_2, + mortgageInterestRate: history.mortgage_interest_rate, + mortgageInterestRateType: history.mortgage_interest_rate_type, + mortgageLenderCode: history.mortgage_lender_code, + mortgageRate: history.mortgage_rate, + mortgageRate2: history.mortgage_rate_2, + mortgageRecordingDate: history.mortgage_recording_date, + mortgageRecordingDate2: history.mortgage_recording_date_2, + mortgageTerm: history.mortgage_term, + mortgageTerm2: history.mortgage_term_2, + mortgageTermType: history.mortgage_term_type, + mortgageTermType2: history.mortgage_term_type_2, + mortgageType: history.mortgage_type, + mortgageType2: history.mortgage_type_2, + multiParcelFlag: history.multi_parcel_flag, + nameTitleCompany: history.name_title_company, + recordingDate: history.recording_date, + transferAmount: history.transfer_amount, + }; + }); + this.attributes.homeownerTaxExemption = responseData.attributes.homeowner_tax_exemption; + this.attributes.marketImprovementPercent = responseData.attributes.market_improvement_percent; + this.attributes.marketImprovementValue = responseData.attributes.market_improvement_value; + this.attributes.marketLandValue = responseData.attributes.market_land_value; + this.attributes.marketValueYear = responseData.attributes.market_value_year; + this.attributes.matchType = responseData.attributes.match_type; + this.attributes.otherTaxExemption = responseData.attributes.other_tax_exemption; + this.attributes.ownershipTransferDate = responseData.attributes.ownership_transfer_date; + this.attributes.ownershipTransferDocNumber = + responseData.attributes.ownership_transfer_doc_number; + this.attributes.ownershipTransferTransactionId = + responseData.attributes.ownership_transfer_transaction_id; + this.attributes.ownershipType = responseData.attributes.ownership_type; + this.attributes.ownershipType2 = responseData.attributes.ownership_type_2; + this.attributes.previousAssessedValue = responseData.attributes.previous_assessed_value; + this.attributes.priorSaleAmount = responseData.attributes.prior_sale_amount; + this.attributes.priorSaleDate = responseData.attributes.prior_sale_date; + this.attributes.saleAmount = responseData.attributes.sale_amount; + this.attributes.saleDate = responseData.attributes.sale_date; + this.attributes.seniorTaxExemption = responseData.attributes.senior_tax_exemption; + this.attributes.taxAssessYear = responseData.attributes.tax_assess_year; + this.attributes.taxBilledAmount = responseData.attributes.tax_billed_amount; + this.attributes.taxDelinquentYear = responseData.attributes.tax_delinquent_year; + this.attributes.taxFiscalYear = responseData.attributes.tax_fiscal_year; + this.attributes.taxRateArea = responseData.attributes.tax_rate_area; + this.attributes.totalMarketValue = responseData.attributes.total_market_value; + this.attributes.trustDescription = responseData.attributes.trust_description; + this.attributes.veteranTaxExemption = responseData.attributes.veteran_tax_exemption; + this.attributes.widowTaxExemption = responseData.attributes.widow_tax_exemption; + } + } +} + +export class GeoResponse { + smartyKey: string; + dataSetName: string; + attributes: GeoAttributes; + + constructor(responseData: RawGeoResponse) { + this.smartyKey = responseData.smarty_key ?? ""; + this.dataSetName = responseData.data_set_name ?? ""; + + this.attributes = {} as GeoAttributes; + if (responseData.attributes) { + const censusBlock: GeoCensusBlock = {} as GeoCensusBlock; + if (responseData.attributes.census_block) { + censusBlock.accuracy = responseData.attributes.census_block.accuracy; + censusBlock.geoid = responseData.attributes.census_block.geoid; + } + this.attributes.censusBlock = censusBlock; + + const censusCountyDivision: GeoCensusCountyDivision = {} as GeoCensusCountyDivision; + if (responseData.attributes.census_county_division) { + censusCountyDivision.accuracy = responseData.attributes.census_county_division.accuracy; + censusCountyDivision.code = responseData.attributes.census_county_division.code; + censusCountyDivision.name = responseData.attributes.census_county_division.name; + } + this.attributes.censusCountyDivision = censusCountyDivision; + + const censusTract: GeoCensusTract = {} as GeoCensusTract; + if (responseData.attributes.census_tract) { + censusTract.code = responseData.attributes.census_tract.code; + } + this.attributes.censusTract = censusTract; + + const coreBasedStatArea: GeoCoreBasedStatArea = {} as GeoCoreBasedStatArea; + if (responseData.attributes.core_based_stat_area) { + coreBasedStatArea.code = responseData.attributes.core_based_stat_area.code; + coreBasedStatArea.name = responseData.attributes.core_based_stat_area.name; + } + this.attributes.coreBasedStatArea = coreBasedStatArea; + + const place: GeoPlace = {} as GeoPlace; + if (responseData.attributes.place) { + place.accuracy = responseData.attributes.place.accuracy; + place.code = responseData.attributes.place.code; + place.name = responseData.attributes.place.name; + place.type = responseData.attributes.place.type; + } + this.attributes.place = place; + } + } +} + +export default { + Response, + FinancialResponse, + GeoResponse, +}; diff --git a/src/us_extract/Address.js b/src/us_extract/Address.js deleted file mode 100644 index e800e4c..0000000 --- a/src/us_extract/Address.js +++ /dev/null @@ -1,17 +0,0 @@ -const Candidate = require("../us_street/Candidate"); - -/** - * @see Smarty US Extract API docs - */ -class Address { - constructor (responseData) { - this.text = responseData.text; - this.verified = responseData.verified; - this.line = responseData.line; - this.start = responseData.start; - this.end = responseData.end; - this.candidates = responseData.api_output.map(rawAddress => new Candidate(rawAddress)); - } -} - -module.exports = Address; \ No newline at end of file diff --git a/src/us_extract/Address.ts b/src/us_extract/Address.ts new file mode 100644 index 0000000..ed1c87b --- /dev/null +++ b/src/us_extract/Address.ts @@ -0,0 +1,30 @@ +import Candidate, { RawUsStreetCandidate } from "../us_street/Candidate.js"; + +export interface RawExtractAddress { + text?: string; + verified?: boolean; + line?: number; + start?: number; + end?: number; + api_output?: RawUsStreetCandidate[]; +} + +export default class Address { + text: string; + verified: boolean; + line: number; + start: number; + end: number; + candidates: Candidate[]; + + constructor(responseData: RawExtractAddress) { + this.text = responseData.text ?? ""; + this.verified = responseData.verified ?? false; + this.line = responseData.line ?? 0; + this.start = responseData.start ?? 0; + this.end = responseData.end ?? 0; + this.candidates = responseData.api_output + ? responseData.api_output.map((rawAddress) => new Candidate(rawAddress)) + : []; + } +} diff --git a/src/us_extract/Client.js b/src/us_extract/Client.js deleted file mode 100644 index c2a9202..0000000 --- a/src/us_extract/Client.js +++ /dev/null @@ -1,35 +0,0 @@ -const Errors = require("../Errors"); -const Request = require("../Request"); -const Result = require("./Result"); -const buildInputData = require("../util/buildInputData"); -const keyTranslationFormat = require("../util/apiToSDKKeyMap").usExtract; - -/** - * This client sends lookups to the Smarty US Extract API,
- * and attaches the results to the Lookup objects. - */ -class Client { - constructor(sender) { - this.sender = sender; - } - - send(lookup) { - if (typeof lookup === "undefined") throw new Errors.UndefinedLookupError(); - - let request = new Request(lookup.text, {"Content-Type": "text/plain; charset=utf-8"}); - request.parameters = buildInputData(lookup, keyTranslationFormat); - - return new Promise((resolve, reject) => { - this.sender.send(request) - .then(response => { - if (response.error) reject(response.error); - - lookup.result = new Result(response.payload); - resolve(lookup); - }) - .catch(reject); - }); - } -} - -module.exports = Client; \ No newline at end of file diff --git a/src/us_extract/Client.ts b/src/us_extract/Client.ts new file mode 100644 index 0000000..cc97ade --- /dev/null +++ b/src/us_extract/Client.ts @@ -0,0 +1,51 @@ +import { UndefinedLookupError } from "../Errors.js"; +import Request from "../Request.js"; +import Result from "./Result.js"; +import { RawExtractAddress } from "./Address.js"; +import buildInputData from "../util/buildInputData.js"; +import apiToSDKKeyMap from "../util/apiToSDKKeyMap.js"; +import { Sender } from "../types.js"; +import Lookup from "./Lookup.js"; + +const keyTranslationFormat = apiToSDKKeyMap.usExtract; + +interface RawExtractMeta { + lines?: number; + unicode?: boolean; + address_count?: number; + verified_count?: number; + bytes?: number; + character_count?: number; +} + +export default class Client { + private sender: Sender; + + constructor(sender: Sender) { + this.sender = sender; + } + + send(lookup: Lookup): Promise { + if (typeof lookup === "undefined") throw new UndefinedLookupError(); + + const request = new Request(lookup.text, { "Content-Type": "text/plain; charset=utf-8" }); + request.parameters = buildInputData(lookup, keyTranslationFormat); + + return new Promise((resolve, reject) => { + this.sender + .send(request) + .then((response) => { + if (response.error) return reject(response.error); + + lookup.result = new Result( + response.payload as { + meta: RawExtractMeta; + addresses: RawExtractAddress[]; + }, + ); + resolve(lookup); + }) + .catch(reject); + }); + } +} diff --git a/src/us_extract/Lookup.js b/src/us_extract/Lookup.js deleted file mode 100644 index adf43d4..0000000 --- a/src/us_extract/Lookup.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * In addition to holding all of the input data for this lookup, this class also
- * will contain the result of the lookup after it comes back from the API. - * @see "https://www.smarty.com/docs/cloud/us-extract-api#http-request-input-fields" - */ -class Lookup { - /** - * @param text The text that is to have addresses extracted out of it for verification (required) - */ - constructor(text) { - this.result = { - meta: {}, - addresses: [], - }; - //TODO: require the text field. - this.text = text; - this.html = undefined; - this.aggressive = undefined; - this.addressesHaveLineBreaks = undefined; - this.addressesPerLine = undefined; - this.customParameters = {}; - } - - addCustomParameter(key, value) { - this.customParameters[key] = value; - } -} - -module.exports = Lookup; \ No newline at end of file diff --git a/src/us_extract/Lookup.ts b/src/us_extract/Lookup.ts new file mode 100644 index 0000000..bb9d1ce --- /dev/null +++ b/src/us_extract/Lookup.ts @@ -0,0 +1,25 @@ +import Result from "./Result.js"; + +export default class Lookup { + result: Result; + text: string; + html: boolean | undefined; + aggressive: boolean | undefined; + addressesHaveLineBreaks: boolean | undefined; + addressesPerLine: number | undefined; + customParameters: Record; + + constructor(text: string) { + this.result = new Result({ meta: {}, addresses: [] }); + this.text = text; + this.html = undefined; + this.aggressive = undefined; + this.addressesHaveLineBreaks = undefined; + this.addressesPerLine = undefined; + this.customParameters = {}; + } + + addCustomParameter(key: string, value: string): void { + this.customParameters[key] = value; + } +} diff --git a/src/us_extract/Result.js b/src/us_extract/Result.js deleted file mode 100644 index 73bf2ab..0000000 --- a/src/us_extract/Result.js +++ /dev/null @@ -1,21 +0,0 @@ -const Address = require("./Address"); - -/** - * @see Smarty US Extract API docs - */ -class Result { - constructor({meta, addresses}) { - this.meta = { - lines: meta.lines, - unicode: meta.unicode, - addressCount: meta.address_count, - verifiedCount: meta.verified_count, - bytes: meta.bytes, - characterCount: meta.character_count, - }; - - this.addresses = addresses.map(rawAddress => new Address(rawAddress)); - } -} - -module.exports = Result; \ No newline at end of file diff --git a/src/us_extract/Result.ts b/src/us_extract/Result.ts new file mode 100644 index 0000000..e5fb2a2 --- /dev/null +++ b/src/us_extract/Result.ts @@ -0,0 +1,37 @@ +import Address, { RawExtractAddress } from "./Address.js"; + +export interface ExtractMeta { + lines: number | undefined; + unicode: boolean | undefined; + addressCount: number | undefined; + verifiedCount: number | undefined; + bytes: number | undefined; + characterCount: number | undefined; +} + +interface RawExtractMeta { + lines?: number; + unicode?: boolean; + address_count?: number; + verified_count?: number; + bytes?: number; + character_count?: number; +} + +export default class Result { + meta: ExtractMeta; + addresses: Address[]; + + constructor({ meta, addresses }: { meta: RawExtractMeta; addresses: RawExtractAddress[] }) { + this.meta = { + lines: meta.lines, + unicode: meta.unicode, + addressCount: meta.address_count, + verifiedCount: meta.verified_count, + bytes: meta.bytes, + characterCount: meta.character_count, + }; + + this.addresses = addresses.map((rawAddress) => new Address(rawAddress)); + } +} diff --git a/src/us_reverse_geo/Client.js b/src/us_reverse_geo/Client.js deleted file mode 100644 index 910b236..0000000 --- a/src/us_reverse_geo/Client.js +++ /dev/null @@ -1,40 +0,0 @@ -const Request = require("../Request"); -const Response = require("./Response"); -const buildInputData = require("../util/buildInputData"); -const keyTranslationFormat = require("../util/apiToSDKKeyMap").usReverseGeo; -const {UndefinedLookupError} = require("../Errors.js"); - -/** - * This client sends lookups to the Smarty US Reverse Geo API,
- * and attaches the results to the appropriate Lookup objects. - */ -class Client { - constructor(sender) { - this.sender = sender; - } - - send(lookup) { - if (typeof lookup === "undefined") throw new UndefinedLookupError(); - - let request = new Request(); - request.parameters = buildInputData(lookup, keyTranslationFormat); - - return new Promise((resolve, reject) => { - this.sender.send(request) - .then(response => { - if (response.error) reject(response.error); - - resolve(attachLookupResults(response, lookup)); - }) - .catch(reject); - }); - - function attachLookupResults(response, lookup) { - lookup.response = new Response(response.payload); - - return lookup; - } - } -} - -module.exports = Client; diff --git a/src/us_reverse_geo/Client.ts b/src/us_reverse_geo/Client.ts new file mode 100644 index 0000000..d2118bf --- /dev/null +++ b/src/us_reverse_geo/Client.ts @@ -0,0 +1,42 @@ +import Request from "../Request.js"; +import Response from "./Response.js"; +import { RawReverseGeoResult } from "./Result.js"; +import buildInputData from "../util/buildInputData.js"; +import apiToSDKKeyMap from "../util/apiToSDKKeyMap.js"; +import { UndefinedLookupError } from "../Errors.js"; +import { Sender, Response as SdkResponse } from "../types.js"; +import Lookup from "./Lookup.js"; + +const keyTranslationFormat = apiToSDKKeyMap.usReverseGeo; + +export default class Client { + private sender: Sender; + + constructor(sender: Sender) { + this.sender = sender; + } + + send(lookup: Lookup): Promise { + if (typeof lookup === "undefined") throw new UndefinedLookupError(); + + const request = new Request(); + request.parameters = buildInputData(lookup, keyTranslationFormat); + + return new Promise((resolve, reject) => { + this.sender + .send(request) + .then((response) => { + if (response.error) return reject(response.error); + + resolve(attachLookupResults(response, lookup)); + }) + .catch(reject); + }); + + function attachLookupResults(response: SdkResponse, lookup: Lookup): Lookup { + lookup.response = new Response(response.payload as { results: RawReverseGeoResult[] }); + + return lookup; + } + } +} diff --git a/src/us_reverse_geo/Lookup.js b/src/us_reverse_geo/Lookup.js deleted file mode 100644 index abb36da..0000000 --- a/src/us_reverse_geo/Lookup.js +++ /dev/null @@ -1,22 +0,0 @@ -const Response = require("./Response"); - -/** - * In addition to holding all of the input data for this lookup, this class also
- * will contain the result of the lookup after it comes back from the API. - * @see "https://www.smarty.com/docs/cloud/us-street-api#input-fields" - */ -class Lookup { - constructor(latitude, longitude, source="") { - this.latitude = latitude.toFixed(8); - this.longitude = longitude.toFixed(8); - this.source = source; - this.response = new Response(); - this.customParameters = {}; - } - - addCustomParameter(key, value) { - this.customParameters[key] = value; - } -} - -module.exports = Lookup; diff --git a/src/us_reverse_geo/Lookup.ts b/src/us_reverse_geo/Lookup.ts new file mode 100644 index 0000000..53fb25c --- /dev/null +++ b/src/us_reverse_geo/Lookup.ts @@ -0,0 +1,21 @@ +import Response from "./Response.js"; + +export default class Lookup { + latitude: string; + longitude: string; + source: string; + response: Response; + customParameters: Record; + + constructor(latitude: number, longitude: number, source: string = "") { + this.latitude = latitude.toFixed(8); + this.longitude = longitude.toFixed(8); + this.source = source; + this.response = new Response(); + this.customParameters = {}; + } + + addCustomParameter(key: string, value: string): void { + this.customParameters[key] = value; + } +} diff --git a/src/us_reverse_geo/Response.js b/src/us_reverse_geo/Response.js deleted file mode 100644 index a226fdb..0000000 --- a/src/us_reverse_geo/Response.js +++ /dev/null @@ -1,17 +0,0 @@ -const Result = require("./Result"); - -/** - * The SmartyResponse contains the response from a call to the US Reverse Geo API. - */ -class Response { - constructor(responseData) { - this.results = []; - - if (responseData) - responseData.results.map(rawResult => { - this.results.push(new Result(rawResult)); - }); - } -} - -module.exports = Response; diff --git a/src/us_reverse_geo/Response.ts b/src/us_reverse_geo/Response.ts new file mode 100644 index 0000000..393faa4 --- /dev/null +++ b/src/us_reverse_geo/Response.ts @@ -0,0 +1,18 @@ +import Result, { RawReverseGeoResult } from "./Result.js"; + +interface RawReverseGeoResponse { + results: RawReverseGeoResult[]; +} + +export default class Response { + results: Result[]; + + constructor(responseData?: RawReverseGeoResponse) { + this.results = []; + + if (responseData) + responseData.results.forEach((rawResult: RawReverseGeoResult) => { + this.results.push(new Result(rawResult)); + }); + } +} diff --git a/src/us_reverse_geo/Result.js b/src/us_reverse_geo/Result.js deleted file mode 100644 index f20cd4f..0000000 --- a/src/us_reverse_geo/Result.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * A candidate is a possible match for an address that was submitted.
- * A lookup can have multiple candidates if the address was ambiguous. - * - * @see "https://www.smarty.com/docs/cloud/us-reverse-geo-api#result" - */ -class Result { - constructor(responseData) { - this.distance = responseData.distance; - - this.address = {}; - if (responseData.address) { - this.address.street = responseData.address.street; - this.address.city = responseData.address.city; - this.address.state_abbreviation = responseData.address.state_abbreviation; - this.address.zipcode = responseData.address.zipcode; - this.address.source = responseData.address.source - } - - this.coordinate = {}; - if (responseData.coordinate) { - this.coordinate.latitude = responseData.coordinate.latitude; - this.coordinate.longitude = responseData.coordinate.longitude; - this.coordinate.accuracy = responseData.coordinate.accuracy; - switch (responseData.coordinate.license) { - case 1: - this.coordinate.license = "SmartyStreets Proprietary"; - break; - default: - this.coordinate.license = "SmartyStreets"; - } - } - } -} - -module.exports = Result; \ No newline at end of file diff --git a/src/us_reverse_geo/Result.ts b/src/us_reverse_geo/Result.ts new file mode 100644 index 0000000..519f6b6 --- /dev/null +++ b/src/us_reverse_geo/Result.ts @@ -0,0 +1,73 @@ +import type { CoordinateLicense } from "../us_street/Candidate.js"; + +export interface ReverseGeoAddress { + street: string | undefined; + city: string | undefined; + stateAbbreviation: string | undefined; + zipcode: string | undefined; + source: string | undefined; + smartyKey: string | undefined; +} + +export interface ReverseGeoCoordinate { + latitude: number | undefined; + longitude: number | undefined; + accuracy: string | undefined; + license: CoordinateLicense | undefined; +} + +interface RawReverseGeoAddress { + street?: string; + city?: string; + state_abbreviation?: string; + zipcode?: string; + source?: string; + smarty_key?: string; +} + +interface RawReverseGeoCoordinate { + latitude?: number; + longitude?: number; + accuracy?: string; + license?: number; +} + +export interface RawReverseGeoResult { + distance?: number; + address?: RawReverseGeoAddress; + coordinate?: RawReverseGeoCoordinate; +} + +export default class Result { + distance: number; + address: ReverseGeoAddress; + coordinate: ReverseGeoCoordinate; + + constructor(responseData: RawReverseGeoResult) { + this.distance = responseData.distance ?? 0; + + this.address = {} as ReverseGeoAddress; + if (responseData.address) { + this.address.street = responseData.address.street; + this.address.city = responseData.address.city; + this.address.stateAbbreviation = responseData.address.state_abbreviation; + this.address.zipcode = responseData.address.zipcode; + this.address.source = responseData.address.source; + this.address.smartyKey = responseData.address.smarty_key; + } + + this.coordinate = {} as ReverseGeoCoordinate; + if (responseData.coordinate) { + this.coordinate.latitude = responseData.coordinate.latitude; + this.coordinate.longitude = responseData.coordinate.longitude; + this.coordinate.accuracy = responseData.coordinate.accuracy; + switch (responseData.coordinate.license) { + case 1: + this.coordinate.license = "SmartyStreets Proprietary"; + break; + default: + this.coordinate.license = "SmartyStreets"; + } + } + } +} diff --git a/src/us_street/Candidate.js b/src/us_street/Candidate.js deleted file mode 100644 index eb160cf..0000000 --- a/src/us_street/Candidate.js +++ /dev/null @@ -1,112 +0,0 @@ -/** - * A candidate is a possible match for an address that was submitted.
- * A lookup can have multiple candidates if the address was ambiguous, and
- * the maxCandidates field is set higher than 1. - * - * @see "https://www.smarty.com/docs/cloud/us-street-api#root" - */ -class Candidate { - constructor(responseData) { - this.inputIndex = responseData.input_index; - this.candidateIndex = responseData.candidate_index; - this.addressee = responseData.addressee; - this.deliveryLine1 = responseData.delivery_line_1; - this.deliveryLine2 = responseData.delivery_line_2; - this.lastLine = responseData.last_line; - this.deliveryPointBarcode = responseData.delivery_point_barcode; - this.smartyKey = responseData.smarty_key; - - this.components = {}; - if (responseData.components !== undefined) { - this.components.urbanization = responseData.components.urbanization; - this.components.primaryNumber = responseData.components.primary_number; - this.components.streetName = responseData.components.street_name; - this.components.streetPredirection = responseData.components.street_predirection; - this.components.streetPostdirection = responseData.components.street_postdirection; - this.components.streetSuffix = responseData.components.street_suffix; - this.components.secondaryNumber = responseData.components.secondary_number; - this.components.secondaryDesignator = responseData.components.secondary_designator; - this.components.extraSecondaryNumber = responseData.components.extra_secondary_number; - this.components.extraSecondaryDesignator = responseData.components.extra_secondary_designator; - this.components.pmbDesignator = responseData.components.pmb_designator; - this.components.pmbNumber = responseData.components.pmb_number; - this.components.cityName = responseData.components.city_name; - this.components.defaultCityName = responseData.components.default_city_name; - this.components.state = responseData.components.state_abbreviation; - this.components.zipCode = responseData.components.zipcode; - this.components.plus4Code = responseData.components.plus4_code; - this.components.deliveryPoint = responseData.components.delivery_point; - this.components.deliveryPointCheckDigit = responseData.components.delivery_point_check_digit; - } - - this.metadata = {}; - if (responseData.metadata !== undefined) { - this.metadata.recordType = responseData.metadata.record_type; - this.metadata.zipType = responseData.metadata.zip_type; - this.metadata.countyFips = responseData.metadata.county_fips; - this.metadata.countyName = responseData.metadata.county_name; - this.metadata.carrierRoute = responseData.metadata.carrier_route; - this.metadata.congressionalDistrict = responseData.metadata.congressional_district; - this.metadata.buildingDefaultIndicator = responseData.metadata.building_default_indicator; - this.metadata.rdi = responseData.metadata.rdi; - this.metadata.elotSequence = responseData.metadata.elot_sequence; - this.metadata.elotSort = responseData.metadata.elot_sort; - this.metadata.latitude = responseData.metadata.latitude; - this.metadata.longitude = responseData.metadata.longitude; - switch (responseData.metadata.coordinate_license) { - case 1: - this.metadata.coordinateLicense = "SmartyStreets Proprietary"; - break; - default: - this.metadata.coordinateLicense = "SmartyStreets"; - } - this.metadata.precision = responseData.metadata.precision; - this.metadata.timeZone = responseData.metadata.time_zone; - this.metadata.utcOffset = responseData.metadata.utc_offset; - this.metadata.obeysDst = responseData.metadata.dst; - this.metadata.isEwsMatch = responseData.metadata.ews_match; - } - - this.analysis = {}; - if (responseData.analysis !== undefined) { - this.analysis.dpvMatchCode = responseData.analysis.dpv_match_code; - this.analysis.dpvFootnotes = responseData.analysis.dpv_footnotes; - this.analysis.cmra = responseData.analysis.dpv_cmra; - this.analysis.vacant = responseData.analysis.dpv_vacant; - this.analysis.noStat = responseData.analysis.dpv_no_stat; - this.analysis.active = responseData.analysis.active; - this.analysis.isEwsMatch = responseData.analysis.ews_match; // Deprecated, refer to metadata.ews_match - this.analysis.footnotes = responseData.analysis.footnotes; - this.analysis.lacsLinkCode = responseData.analysis.lacslink_code; - this.analysis.lacsLinkIndicator = responseData.analysis.lacslink_indicator; - this.analysis.isSuiteLinkMatch = responseData.analysis.suitelink_match; - this.analysis.enhancedMatch = responseData.analysis.enhanced_match; - this.analysis.components = {}; - if (responseData.analysis.components !== undefined) { - this.analysis.components.primaryNumber = responseData.analysis.components.primary_number; - this.analysis.components.streetPredirection = - responseData.analysis.components.street_predirection; - this.analysis.components.streetName = responseData.analysis.components.street_name; - this.analysis.components.streetPostdirection = - responseData.analysis.components.street_postdirection; - this.analysis.components.streetSuffix = responseData.analysis.components.street_suffix; - this.analysis.components.secondaryNumber = - responseData.analysis.components.secondary_number; - this.analysis.components.secondaryDesignator = - responseData.analysis.components.secondary_designator; - this.analysis.components.extraSecondaryNumber = - responseData.analysis.components.extra_secondary_number; - this.analysis.components.extraSecondaryDesignator = - responseData.analysis.components.extra_secondary_designator; - this.analysis.components.cityName = responseData.analysis.components.city_name; - this.analysis.components.stateAbbreviation = - responseData.analysis.components.state_abbreviation; - this.analysis.components.zipCode = responseData.analysis.components.zipcode; - this.analysis.components.plus4Code = responseData.analysis.components.plus4_code; - this.analysis.components.urbanization = responseData.analysis.components.urbanization; - } - } - } -} - -module.exports = Candidate; diff --git a/src/us_street/Candidate.ts b/src/us_street/Candidate.ts new file mode 100644 index 0000000..f3463d2 --- /dev/null +++ b/src/us_street/Candidate.ts @@ -0,0 +1,317 @@ +export type CoordinateLicense = "SmartyStreets" | "SmartyStreets Proprietary" | (string & {}); + +export interface MatchInfo { + status: string | undefined; + change: string[] | undefined; +} + +export interface UsStreetComponents { + urbanization: string | undefined; + primaryNumber: string | undefined; + streetName: string | undefined; + streetPredirection: string | undefined; + streetPostdirection: string | undefined; + streetSuffix: string | undefined; + secondaryNumber: string | undefined; + secondaryDesignator: string | undefined; + extraSecondaryNumber: string | undefined; + extraSecondaryDesignator: string | undefined; + pmbDesignator: string | undefined; + pmbNumber: string | undefined; + cityName: string | undefined; + defaultCityName: string | undefined; + state: string | undefined; + zipCode: string | undefined; + plus4Code: string | undefined; + deliveryPoint: string | undefined; + deliveryPointCheckDigit: string | undefined; +} + +export interface UsStreetMetadata { + recordType: string | undefined; + zipType: string | undefined; + countyFips: string | undefined; + countyName: string | undefined; + carrierRoute: string | undefined; + congressionalDistrict: string | undefined; + buildingDefaultIndicator: string | undefined; + rdi: string | undefined; + elotSequence: string | undefined; + elotSort: string | undefined; + latitude: number | undefined; + longitude: number | undefined; + coordinateLicense: CoordinateLicense | undefined; + precision: string | undefined; + timeZone: string | undefined; + utcOffset: number | undefined; + obeysDst: boolean | undefined; + isEwsMatch: boolean | undefined; +} + +export interface AnalysisComponents { + primaryNumber: MatchInfo; + streetPredirection: MatchInfo; + streetName: MatchInfo; + streetPostdirection: MatchInfo; + streetSuffix: MatchInfo; + secondaryNumber: MatchInfo; + secondaryDesignator: MatchInfo; + extraSecondaryNumber: MatchInfo; + extraSecondaryDesignator: MatchInfo; + cityName: MatchInfo; + stateAbbreviation: MatchInfo; + zipCode: MatchInfo; + plus4Code: MatchInfo; + urbanization: MatchInfo; +} + +export interface UsStreetAnalysis { + dpvMatchCode: string | undefined; + dpvFootnotes: string | undefined; + cmra: string | undefined; + vacant: string | undefined; + noStat: string | undefined; + active: string | undefined; + isEwsMatch: boolean | undefined; + footnotes: string | undefined; + lacsLinkCode: string | undefined; + lacsLinkIndicator: string | undefined; + isSuiteLinkMatch: boolean | undefined; + enhancedMatch: string | undefined; + components: AnalysisComponents; +} + +interface RawUsStreetComponents { + urbanization?: string; + primary_number?: string; + street_name?: string; + street_predirection?: string; + street_postdirection?: string; + street_suffix?: string; + secondary_number?: string; + secondary_designator?: string; + extra_secondary_number?: string; + extra_secondary_designator?: string; + pmb_designator?: string; + pmb_number?: string; + city_name?: string; + default_city_name?: string; + state_abbreviation?: string; + zipcode?: string; + plus4_code?: string; + delivery_point?: string; + delivery_point_check_digit?: string; +} + +interface RawUsStreetMetadata { + record_type?: string; + zip_type?: string; + county_fips?: string; + county_name?: string; + carrier_route?: string; + congressional_district?: string; + building_default_indicator?: string; + rdi?: string; + elot_sequence?: string; + elot_sort?: string; + latitude?: number; + longitude?: number; + coordinate_license?: number; + precision?: string; + time_zone?: string; + utc_offset?: number; + dst?: boolean; + ews_match?: boolean; +} + +interface RawMatchInfo { + status?: string; + change?: string[]; +} + +interface RawUsStreetAnalysisComponents { + primary_number?: RawMatchInfo; + street_predirection?: RawMatchInfo; + street_name?: RawMatchInfo; + street_postdirection?: RawMatchInfo; + street_suffix?: RawMatchInfo; + secondary_number?: RawMatchInfo; + secondary_designator?: RawMatchInfo; + extra_secondary_number?: RawMatchInfo; + extra_secondary_designator?: RawMatchInfo; + city_name?: RawMatchInfo; + state_abbreviation?: RawMatchInfo; + zipcode?: RawMatchInfo; + plus4_code?: RawMatchInfo; + urbanization?: RawMatchInfo; +} + +interface RawUsStreetAnalysis { + dpv_match_code?: string; + dpv_footnotes?: string; + dpv_cmra?: string; + dpv_vacant?: string; + dpv_no_stat?: string; + active?: string; + ews_match?: boolean; + footnotes?: string; + lacslink_code?: string; + lacslink_indicator?: string; + suitelink_match?: boolean; + enhanced_match?: string; + components?: RawUsStreetAnalysisComponents; +} + +export interface RawUsStreetCandidate { + input_id?: string; + input_index?: number; + candidate_index?: number; + addressee?: string; + delivery_line_1?: string; + delivery_line_2?: string; + last_line?: string; + delivery_point_barcode?: string; + smarty_key?: string; + components?: RawUsStreetComponents; + metadata?: RawUsStreetMetadata; + analysis?: RawUsStreetAnalysis; +} + +export default class Candidate { + inputId: string; + inputIndex: number; + candidateIndex: number; + addressee: string; + deliveryLine1: string; + deliveryLine2: string; + lastLine: string; + deliveryPointBarcode: string; + smartyKey: string; + components: UsStreetComponents; + metadata: UsStreetMetadata; + analysis: UsStreetAnalysis; + + constructor(responseData: RawUsStreetCandidate) { + this.inputId = responseData.input_id ?? ""; + this.inputIndex = responseData.input_index ?? 0; + this.candidateIndex = responseData.candidate_index ?? 0; + this.addressee = responseData.addressee ?? ""; + this.deliveryLine1 = responseData.delivery_line_1 ?? ""; + this.deliveryLine2 = responseData.delivery_line_2 ?? ""; + this.lastLine = responseData.last_line ?? ""; + this.deliveryPointBarcode = responseData.delivery_point_barcode ?? ""; + this.smartyKey = responseData.smarty_key ?? ""; + + this.components = {} as UsStreetComponents; + if (responseData.components !== undefined) { + this.components.urbanization = responseData.components.urbanization; + this.components.primaryNumber = responseData.components.primary_number; + this.components.streetName = responseData.components.street_name; + this.components.streetPredirection = responseData.components.street_predirection; + this.components.streetPostdirection = responseData.components.street_postdirection; + this.components.streetSuffix = responseData.components.street_suffix; + this.components.secondaryNumber = responseData.components.secondary_number; + this.components.secondaryDesignator = responseData.components.secondary_designator; + this.components.extraSecondaryNumber = responseData.components.extra_secondary_number; + this.components.extraSecondaryDesignator = responseData.components.extra_secondary_designator; + this.components.pmbDesignator = responseData.components.pmb_designator; + this.components.pmbNumber = responseData.components.pmb_number; + this.components.cityName = responseData.components.city_name; + this.components.defaultCityName = responseData.components.default_city_name; + this.components.state = responseData.components.state_abbreviation; + this.components.zipCode = responseData.components.zipcode; + this.components.plus4Code = responseData.components.plus4_code; + this.components.deliveryPoint = responseData.components.delivery_point; + this.components.deliveryPointCheckDigit = responseData.components.delivery_point_check_digit; + } + + this.metadata = {} as UsStreetMetadata; + if (responseData.metadata !== undefined) { + this.metadata.recordType = responseData.metadata.record_type; + this.metadata.zipType = responseData.metadata.zip_type; + this.metadata.countyFips = responseData.metadata.county_fips; + this.metadata.countyName = responseData.metadata.county_name; + this.metadata.carrierRoute = responseData.metadata.carrier_route; + this.metadata.congressionalDistrict = responseData.metadata.congressional_district; + this.metadata.buildingDefaultIndicator = responseData.metadata.building_default_indicator; + this.metadata.rdi = responseData.metadata.rdi; + this.metadata.elotSequence = responseData.metadata.elot_sequence; + this.metadata.elotSort = responseData.metadata.elot_sort; + this.metadata.latitude = responseData.metadata.latitude; + this.metadata.longitude = responseData.metadata.longitude; + switch (responseData.metadata.coordinate_license) { + case 1: + this.metadata.coordinateLicense = "SmartyStreets Proprietary"; + break; + default: + this.metadata.coordinateLicense = "SmartyStreets"; + } + this.metadata.precision = responseData.metadata.precision; + this.metadata.timeZone = responseData.metadata.time_zone; + this.metadata.utcOffset = responseData.metadata.utc_offset; + this.metadata.obeysDst = responseData.metadata.dst; + this.metadata.isEwsMatch = responseData.metadata.ews_match; + } + + this.analysis = {} as UsStreetAnalysis; + if (responseData.analysis !== undefined) { + this.analysis.dpvMatchCode = responseData.analysis.dpv_match_code; + this.analysis.dpvFootnotes = responseData.analysis.dpv_footnotes; + this.analysis.cmra = responseData.analysis.dpv_cmra; + this.analysis.vacant = responseData.analysis.dpv_vacant; + this.analysis.noStat = responseData.analysis.dpv_no_stat; + this.analysis.active = responseData.analysis.active; + this.analysis.isEwsMatch = responseData.analysis.ews_match; // Deprecated, refer to metadata.ews_match + this.analysis.footnotes = responseData.analysis.footnotes; + this.analysis.lacsLinkCode = responseData.analysis.lacslink_code; + this.analysis.lacsLinkIndicator = responseData.analysis.lacslink_indicator; + this.analysis.isSuiteLinkMatch = responseData.analysis.suitelink_match; + this.analysis.enhancedMatch = responseData.analysis.enhanced_match; + this.analysis.components = {} as AnalysisComponents; + if (responseData.analysis.components !== undefined) { + const toMatchInfo = (raw?: RawMatchInfo): MatchInfo => ({ + status: raw?.status, + change: raw?.change, + }); + this.analysis.components.primaryNumber = toMatchInfo( + responseData.analysis.components.primary_number, + ); + this.analysis.components.streetPredirection = toMatchInfo( + responseData.analysis.components.street_predirection, + ); + this.analysis.components.streetName = toMatchInfo( + responseData.analysis.components.street_name, + ); + this.analysis.components.streetPostdirection = toMatchInfo( + responseData.analysis.components.street_postdirection, + ); + this.analysis.components.streetSuffix = toMatchInfo( + responseData.analysis.components.street_suffix, + ); + this.analysis.components.secondaryNumber = toMatchInfo( + responseData.analysis.components.secondary_number, + ); + this.analysis.components.secondaryDesignator = toMatchInfo( + responseData.analysis.components.secondary_designator, + ); + this.analysis.components.extraSecondaryNumber = toMatchInfo( + responseData.analysis.components.extra_secondary_number, + ); + this.analysis.components.extraSecondaryDesignator = toMatchInfo( + responseData.analysis.components.extra_secondary_designator, + ); + this.analysis.components.cityName = toMatchInfo(responseData.analysis.components.city_name); + this.analysis.components.stateAbbreviation = toMatchInfo( + responseData.analysis.components.state_abbreviation, + ); + this.analysis.components.zipCode = toMatchInfo(responseData.analysis.components.zipcode); + this.analysis.components.plus4Code = toMatchInfo( + responseData.analysis.components.plus4_code, + ); + this.analysis.components.urbanization = toMatchInfo( + responseData.analysis.components.urbanization, + ); + } + } + } +} diff --git a/src/us_street/Client.js b/src/us_street/Client.js deleted file mode 100644 index e9ab0e5..0000000 --- a/src/us_street/Client.js +++ /dev/null @@ -1,41 +0,0 @@ -const Candidate = require("./Candidate"); -const Lookup = require("./Lookup"); -const Batch = require("../Batch"); -const UndefinedLookupError = require("../Errors").UndefinedLookupError; -const sendBatch = require("../util/sendBatch"); -const buildUsStreetInputData = require("../util/buildUsStreetInputData"); - -/** - * This client sends lookups to the Smarty US Street API,
- * and attaches the results to the appropriate Lookup objects. - */ -class Client { - constructor(sender) { - this.sender = sender; - } - - /** - * Sends up to 100 lookups for validation. - * @param data may be a Lookup object, or a Batch which must contain between 1 and 100 Lookup objects - * @throws SmartyException - */ - send(data) { - const dataIsBatch = data instanceof Batch; - const dataIsLookup = data instanceof Lookup; - - if (!dataIsLookup && !dataIsBatch) throw new UndefinedLookupError; - - let batch; - - if (dataIsLookup) { - batch = new Batch(); - batch.add(data); - } else { - batch = data; - } - - return sendBatch(batch, this.sender, Candidate, null, buildUsStreetInputData); - } -} - -module.exports = Client; \ No newline at end of file diff --git a/src/us_street/Client.ts b/src/us_street/Client.ts new file mode 100644 index 0000000..d7e35fa --- /dev/null +++ b/src/us_street/Client.ts @@ -0,0 +1,33 @@ +import Candidate from "./Candidate.js"; +import Lookup from "./Lookup.js"; +import Batch from "../Batch.js"; +import { UndefinedLookupError } from "../Errors.js"; +import sendBatch from "../util/sendBatch.js"; +import buildUsStreetInputData from "../util/buildUsStreetInputData.js"; +import { Sender } from "../types.js"; + +export default class Client { + private sender: Sender; + + constructor(sender: Sender) { + this.sender = sender; + } + + send(data: Lookup | Batch): Promise { + const dataIsBatch = data instanceof Batch; + const dataIsLookup = data instanceof Lookup; + + if (!dataIsLookup && !dataIsBatch) throw new UndefinedLookupError(); + + let batch: Batch; + + if (dataIsLookup) { + batch = new Batch(); + batch.add(data); + } else { + batch = data; + } + + return sendBatch(batch, this.sender, Candidate, null, buildUsStreetInputData); + } +} diff --git a/src/us_street/Lookup.js b/src/us_street/Lookup.js deleted file mode 100644 index 59d2a61..0000000 --- a/src/us_street/Lookup.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * In addition to holding all of the input data for this lookup, this class also
- * will contain the result of the lookup after it comes back from the API. - * @see "https://www.smarty.com/docs/cloud/us-street-api#input-fields" - */ -class Lookup { - constructor( - street, - street2, - secondary, - city, - state, - zipCode, - lastLine, - addressee, - urbanization, - match, - maxCandidates, - inputId, - format, - countySource, - ) { - this.street = street; - this.street2 = street2; - this.secondary = secondary; - this.city = city; - this.state = state; - this.zipCode = zipCode; - this.lastLine = lastLine; - this.addressee = addressee; - this.urbanization = urbanization; - this.match = match; - this.maxCandidates = maxCandidates; - this.inputId = inputId; - this.format = format; - this.countySource = countySource; - this.result = []; - this.customParameters = {}; - } - - addCustomParameter(key, value) { - this.customParameters[key] = value; - } - -} - -module.exports = Lookup; diff --git a/src/us_street/Lookup.ts b/src/us_street/Lookup.ts new file mode 100644 index 0000000..c904200 --- /dev/null +++ b/src/us_street/Lookup.ts @@ -0,0 +1,62 @@ +import Candidate from "./Candidate.js"; + +export type MatchStrategy = "strict" | "invalid" | "enhanced" | (string & {}); +export type OutputFormat = "default" | "project-usa" | (string & {}); +export type CountySource = "postal" | "geographic" | (string & {}); + +export default class Lookup { + street: string | undefined; + street2: string | undefined; + secondary: string | undefined; + city: string | undefined; + state: string | undefined; + zipCode: string | undefined; + lastLine: string | undefined; + addressee: string | undefined; + urbanization: string | undefined; + match: MatchStrategy | undefined; + maxCandidates: number | undefined; + inputId: string | undefined; + format: OutputFormat | undefined; + countySource: CountySource | undefined; + result: Candidate[]; + customParameters: Record; + + constructor( + street?: string, + street2?: string, + secondary?: string, + city?: string, + state?: string, + zipCode?: string, + lastLine?: string, + addressee?: string, + urbanization?: string, + match?: MatchStrategy, + maxCandidates?: number, + inputId?: string, + format?: OutputFormat, + countySource?: CountySource, + ) { + this.street = street; + this.street2 = street2; + this.secondary = secondary; + this.city = city; + this.state = state; + this.zipCode = zipCode; + this.lastLine = lastLine; + this.addressee = addressee; + this.urbanization = urbanization; + this.match = match; + this.maxCandidates = maxCandidates; + this.inputId = inputId; + this.format = format; + this.countySource = countySource; + this.result = []; + this.customParameters = {}; + } + + addCustomParameter(key: string, value: string): void { + this.customParameters[key] = value; + } +} diff --git a/src/us_zipcode/Client.js b/src/us_zipcode/Client.js deleted file mode 100644 index 4c81ec3..0000000 --- a/src/us_zipcode/Client.js +++ /dev/null @@ -1,39 +0,0 @@ -const Lookup = require("./Lookup"); -const Result = require("./Result"); -const Batch = require("../Batch"); -const UndefinedLookupError = require("../Errors").UndefinedLookupError; -const sendBatch = require("../util/sendBatch"); -const keyTranslationFormat = require("../util/apiToSDKKeyMap").usZipcode; - -/** - * This client sends lookups to the Smarty US ZIP Code API,
- * and attaches the results to the appropriate Lookup objects. - */ -class Client { - constructor(sender) { - this.sender = sender; - } - - /** - * Sends up to 100 lookups for validation. - * @param data May be a Lookup object, or a Batch which must contain between 1 and 100 Lookup objects - * @throws SmartyException - */ - send(data) { - const dataIsBatch = data instanceof Batch; - const dataIsLookup = data instanceof Lookup; - - if (!dataIsLookup && !dataIsBatch) throw new UndefinedLookupError; - - let batch; - - if (dataIsLookup) { - batch = new Batch(); - batch.add(data); - } else batch = data; - - return sendBatch(batch, this.sender, Result, keyTranslationFormat); - } -} - -module.exports = Client; \ No newline at end of file diff --git a/src/us_zipcode/Client.ts b/src/us_zipcode/Client.ts new file mode 100644 index 0000000..622ac41 --- /dev/null +++ b/src/us_zipcode/Client.ts @@ -0,0 +1,33 @@ +import Lookup from "./Lookup.js"; +import Result from "./Result.js"; +import Batch from "../Batch.js"; +import { UndefinedLookupError } from "../Errors.js"; +import sendBatch from "../util/sendBatch.js"; +import apiToSDKKeyMap from "../util/apiToSDKKeyMap.js"; +import { Sender } from "../types.js"; + +const keyTranslationFormat = apiToSDKKeyMap.usZipcode; + +export default class Client { + private sender: Sender; + + constructor(sender: Sender) { + this.sender = sender; + } + + send(data: Lookup | Batch): Promise { + const dataIsBatch = data instanceof Batch; + const dataIsLookup = data instanceof Lookup; + + if (!dataIsLookup && !dataIsBatch) throw new UndefinedLookupError(); + + let batch: Batch; + + if (dataIsLookup) { + batch = new Batch(); + batch.add(data); + } else batch = data; + + return sendBatch(batch, this.sender, Result, keyTranslationFormat); + } +} diff --git a/src/us_zipcode/Lookup.js b/src/us_zipcode/Lookup.js deleted file mode 100644 index d74c4b4..0000000 --- a/src/us_zipcode/Lookup.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * In addition to holding all of the input data for this lookup, this class also
- * will contain the result of the lookup after it comes back from the API. - * @see "https://www.smarty.com/docs/cloud/us-zipcode-api#http-request-input-fields" - */ -class Lookup { - constructor(city, state, zipCode, inputId) { - this.city = city; - this.state = state; - this.zipCode = zipCode; - this.inputId = inputId; - this.result = []; - this.customParameters = {}; - } - - addCustomParameter(key, value) { - this.customParameters[key] = value; - } -} - -module.exports = Lookup; \ No newline at end of file diff --git a/src/us_zipcode/Lookup.ts b/src/us_zipcode/Lookup.ts new file mode 100644 index 0000000..abe036e --- /dev/null +++ b/src/us_zipcode/Lookup.ts @@ -0,0 +1,23 @@ +import Result from "./Result.js"; + +export default class Lookup { + city: string | undefined; + state: string | undefined; + zipCode: string | undefined; + inputId: string | undefined; + result: Result[]; + customParameters: Record; + + constructor(city?: string, state?: string, zipCode?: string, inputId?: string) { + this.city = city; + this.state = state; + this.zipCode = zipCode; + this.inputId = inputId; + this.result = []; + this.customParameters = {}; + } + + addCustomParameter(key: string, value: string): void { + this.customParameters[key] = value; + } +} diff --git a/src/us_zipcode/Result.js b/src/us_zipcode/Result.js deleted file mode 100644 index 5d7f572..0000000 --- a/src/us_zipcode/Result.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @see "https://www.smarty.com/docs/cloud/us-zipcode-api#root" - */ -class Result { - constructor(responseData) { - this.inputIndex = responseData.input_index; - this.status = responseData.status; - this.reason = responseData.reason; - this.valid = this.status === undefined && this.reason === undefined; - - this.cities = !responseData.city_states ? [] : responseData.city_states.map(city => { - return { - city: city.city, - stateAbbreviation: city.state_abbreviation, - state: city.state, - mailableCity: city.mailable_city, - }; - }); - - this.zipcodes = !responseData.zipcodes ? [] : responseData.zipcodes.map(zipcode => { - return { - zipcode: zipcode.zipcode, - zipcodeType: zipcode.zipcode_type, - defaultCity: zipcode.default_city, - countyFips: zipcode.county_fips, - countyName: zipcode.county_name, - latitude: zipcode.latitude, - longitude: zipcode.longitude, - precision: zipcode.precision, - stateAbbreviation: zipcode.state_abbreviation, - state: zipcode.state, - alternateCounties: !zipcode.alternate_counties ? [] : zipcode.alternate_counties.map(county => { - return { - countyFips: county.county_fips, - countyName: county.county_name, - stateAbbreviation: county.state_abbreviation, - state: county.state, - } - }), - }; - }); - } -} - -module.exports = Result; \ No newline at end of file diff --git a/src/us_zipcode/Result.ts b/src/us_zipcode/Result.ts new file mode 100644 index 0000000..5d704d9 --- /dev/null +++ b/src/us_zipcode/Result.ts @@ -0,0 +1,117 @@ +export interface CityEntry { + city: string; + stateAbbreviation: string; + state: string; + mailableCity: boolean; +} + +export interface AlternateCounty { + countyFips: string; + countyName: string; + stateAbbreviation: string; + state: string; +} + +export interface ZipcodeEntry { + zipcode: string; + zipcodeType: string; + defaultCity: string; + countyFips: string; + countyName: string; + latitude: number; + longitude: number; + precision: string; + stateAbbreviation: string; + state: string; + alternateCounties: AlternateCounty[]; +} + +interface RawAlternateCounty { + county_fips?: string; + county_name?: string; + state_abbreviation?: string; + state?: string; +} + +interface RawCityState { + city?: string; + state_abbreviation?: string; + state?: string; + mailable_city?: boolean; +} + +interface RawZipcode { + zipcode?: string; + zipcode_type?: string; + default_city?: string; + county_fips?: string; + county_name?: string; + latitude?: number; + longitude?: number; + precision?: string; + state_abbreviation?: string; + state?: string; + alternate_counties?: RawAlternateCounty[]; +} + +export interface RawZipcodeResult { + input_index?: number; + status?: string; + reason?: string; + city_states?: RawCityState[]; + zipcodes?: RawZipcode[]; +} + +export default class Result { + inputIndex: number; + status: string | undefined; + reason: string | undefined; + valid: boolean; + cities: CityEntry[]; + zipcodes: ZipcodeEntry[]; + + constructor(responseData: RawZipcodeResult) { + this.inputIndex = responseData.input_index ?? 0; + this.status = responseData.status; + this.reason = responseData.reason; + this.valid = this.status === undefined && this.reason === undefined; + + this.cities = !responseData.city_states + ? [] + : responseData.city_states.map((city): CityEntry => { + return { + city: city.city ?? "", + stateAbbreviation: city.state_abbreviation ?? "", + state: city.state ?? "", + mailableCity: city.mailable_city ?? false, + }; + }); + + this.zipcodes = !responseData.zipcodes + ? [] + : responseData.zipcodes.map((zipcode): ZipcodeEntry => { + return { + zipcode: zipcode.zipcode ?? "", + zipcodeType: zipcode.zipcode_type ?? "", + defaultCity: zipcode.default_city ?? "", + countyFips: zipcode.county_fips ?? "", + countyName: zipcode.county_name ?? "", + latitude: zipcode.latitude ?? 0, + longitude: zipcode.longitude ?? 0, + precision: zipcode.precision ?? "", + stateAbbreviation: zipcode.state_abbreviation ?? "", + state: zipcode.state ?? "", + alternateCounties: !zipcode.alternate_counties + ? [] + : zipcode.alternate_counties.map((county): AlternateCounty => { + return { + countyFips: county.county_fips ?? "", + countyName: county.county_name ?? "", + stateAbbreviation: county.state_abbreviation ?? "", + state: county.state ?? "", + }; + }), + }; + }); + } +} diff --git a/src/util/Sleeper.ts b/src/util/Sleeper.ts index e3a8983..d66a0e2 100644 --- a/src/util/Sleeper.ts +++ b/src/util/Sleeper.ts @@ -1,6 +1,6 @@ export default class Sleeper { - constructor () {} + constructor() {} sleep(seconds: number) { - return new Promise((resolve) => setTimeout(resolve, seconds*1000)); + return new Promise((resolve) => setTimeout(resolve, seconds * 1000)); } -} \ No newline at end of file +} diff --git a/src/util/apiToSDKKeyMap.js b/src/util/apiToSDKKeyMap.js deleted file mode 100644 index 6201311..0000000 --- a/src/util/apiToSDKKeyMap.js +++ /dev/null @@ -1,84 +0,0 @@ -module.exports = { - usStreet: { - "street": "street", - "street2": "street2", - "secondary": "secondary", - "city": "city", - "state": "state", - "zipcode": "zipCode", - "lastline": "lastLine", - "addressee": "addressee", - "urbanization": "urbanization", - "match": "match", - "format": "format", - "candidates": "maxCandidates", - "county_source": "countySource", - "input_id": "inputId" - }, - usAutocompletePro: { - search: "search", - selected: "selected", - max_results: "maxResults", - include_only_cities: "includeOnlyCities", - include_only_states: "includeOnlyStates", - include_only_zip_codes: "includeOnlyZIPCodes", - exclude_states: "excludeStates", - prefer_cities: "preferCities", - prefer_states: "preferStates", - prefer_zip_codes: "preferZIPCodes", - prefer_ratio: "preferRatio", - prefer_geolocation: "preferGeolocation", - source: "source", - }, - usZipcode: { - "city": "city", - "state": "state", - "zipcode": "zipCode", - }, - internationalStreet: { - "country": "country", - "freeform": "freeform", - "address1": "address1", - "address2": "address2", - "address3": "address3", - "address4": "address4", - "organization": "organization", - "locality": "locality", - "administrative_area": "administrativeArea", - "postal_code": "postalCode", - "geocode": "geocode", - "language": "language", - }, - internationalAddressAutocomplete: { - search: "search", - country: "country", - max_results: "maxResults", - include_only_administrative_area: "includeOnlyAdministrativeArea", - include_only_locality: "includeOnlyLocality", - include_only_postal_code: "includeOnlyPostalCode", - }, - usReverseGeo: { - "latitude": "latitude", - "longitude": "longitude", - "source": "source" - }, - usExtract: { - html: "html", - aggressive: "aggressive", - addr_line_breaks: "addressesHaveLineBreaks", - addr_per_line: "addressesPerLine", - }, - usEnrichment: { - include: "include", - exclude: "exclude", - dataset: "dataset", - data_subset: "dataSubset", - }, - internationalPostalCode: { - "input_id": "inputId", - "country": "country", - "locality": "locality", - "administrative_area": "administrativeArea", - "postal_code": "postalCode", - } -}; \ No newline at end of file diff --git a/src/util/apiToSDKKeyMap.ts b/src/util/apiToSDKKeyMap.ts new file mode 100644 index 0000000..33af33f --- /dev/null +++ b/src/util/apiToSDKKeyMap.ts @@ -0,0 +1,98 @@ +interface ApiToSDKKeyMap { + usStreet: Record; + usAutocompletePro: Record; + usZipcode: Record; + internationalStreet: Record; + internationalAddressAutocomplete: Record; + usReverseGeo: Record; + usExtract: Record; + usEnrichment: Record; + internationalPostalCode: Record; +} + +const apiToSDKKeyMap: ApiToSDKKeyMap = { + usStreet: { + street: "street", + street2: "street2", + secondary: "secondary", + city: "city", + state: "state", + zipcode: "zipCode", + lastline: "lastLine", + addressee: "addressee", + urbanization: "urbanization", + match: "match", + format: "format", + candidates: "maxCandidates", + county_source: "countySource", + input_id: "inputId", + }, + usAutocompletePro: { + search: "search", + selected: "selected", + max_results: "maxResults", + include_only_cities: "includeOnlyCities", + include_only_states: "includeOnlyStates", + include_only_zip_codes: "includeOnlyZIPCodes", + exclude_states: "excludeStates", + prefer_cities: "preferCities", + prefer_states: "preferStates", + prefer_zip_codes: "preferZIPCodes", + prefer_ratio: "preferRatio", + prefer_geolocation: "preferGeolocation", + source: "source", + }, + usZipcode: { + city: "city", + state: "state", + zipcode: "zipCode", + }, + internationalStreet: { + country: "country", + freeform: "freeform", + address1: "address1", + address2: "address2", + address3: "address3", + address4: "address4", + organization: "organization", + locality: "locality", + administrative_area: "administrativeArea", + postal_code: "postalCode", + geocode: "geocode", + language: "language", + }, + internationalAddressAutocomplete: { + search: "search", + country: "country", + max_results: "maxResults", + include_only_administrative_area: "includeOnlyAdministrativeArea", + include_only_locality: "includeOnlyLocality", + include_only_postal_code: "includeOnlyPostalCode", + }, + usReverseGeo: { + latitude: "latitude", + longitude: "longitude", + source: "source", + }, + usExtract: { + html: "html", + aggressive: "aggressive", + addr_line_breaks: "addressesHaveLineBreaks", + addr_per_line: "addressesPerLine", + }, + usEnrichment: { + include: "include", + exclude: "exclude", + dataset: "dataset", + data_subset: "dataSubset", + }, + internationalPostalCode: { + input_id: "inputId", + country: "country", + locality: "locality", + administrative_area: "administrativeArea", + postal_code: "postalCode", + }, +}; + +export default apiToSDKKeyMap; diff --git a/src/util/buildClients.js b/src/util/buildClients.ts similarity index 57% rename from src/util/buildClients.js rename to src/util/buildClients.ts index 3e84776..6f2ad55 100644 --- a/src/util/buildClients.js +++ b/src/util/buildClients.ts @@ -1,46 +1,51 @@ -const ClientBuilder = require("../ClientBuilder"); +import ClientBuilder from "../ClientBuilder.js"; +import StaticCredentials from "../StaticCredentials.js"; +import SharedCredentials from "../SharedCredentials.js"; +import BasicAuthCredentials from "../BasicAuthCredentials.js"; -function instantiateClientBuilder(credentials) { +type Credentials = StaticCredentials | SharedCredentials | BasicAuthCredentials; + +function instantiateClientBuilder(credentials: Credentials): ClientBuilder { return new ClientBuilder(credentials); } -function buildUsStreetApiClient(credentials) { +function buildUsStreetApiClient(credentials: Credentials) { return instantiateClientBuilder(credentials).buildUsStreetApiClient(); } -function buildUsAutocompleteProApiClient(credentials) { +function buildUsAutocompleteProApiClient(credentials: Credentials) { return instantiateClientBuilder(credentials).buildUsAutocompleteProClient(); } -function buildUsExtractApiClient(credentials) { +function buildUsExtractApiClient(credentials: Credentials) { return instantiateClientBuilder(credentials).buildUsExtractClient(); } -function buildUsZipcodeApiClient(credentials) { +function buildUsZipcodeApiClient(credentials: Credentials) { return instantiateClientBuilder(credentials).buildUsZipcodeClient(); } -function buildInternationalStreetApiClient(credentials) { +function buildInternationalStreetApiClient(credentials: Credentials) { return instantiateClientBuilder(credentials).buildInternationalStreetClient(); } -function buildUsReverseGeoApiClient(credentials) { +function buildUsReverseGeoApiClient(credentials: Credentials) { return instantiateClientBuilder(credentials).buildUsReverseGeoClient(); } -function buildInternationalAddressAutocompleteApiClient(credentials) { +function buildInternationalAddressAutocompleteApiClient(credentials: Credentials) { return instantiateClientBuilder(credentials).buildInternationalAddressAutocompleteClient(); } -function buildUsEnrichmentApiClient(credentials) { +function buildUsEnrichmentApiClient(credentials: Credentials) { return instantiateClientBuilder(credentials).buildUsEnrichmentClient(); } -function buildInternationalPostalCodeApiClient(credentials) { +function buildInternationalPostalCodeApiClient(credentials: Credentials) { return instantiateClientBuilder(credentials).buildInternationalPostalCodeClient(); } -module.exports = { +export default { usStreet: buildUsStreetApiClient, usAutocompletePro: buildUsAutocompleteProApiClient, usExtract: buildUsExtractApiClient, @@ -50,4 +55,4 @@ module.exports = { internationalAddressAutocomplete: buildInternationalAddressAutocompleteApiClient, usEnrichment: buildUsEnrichmentApiClient, internationalPostalCode: buildInternationalPostalCodeApiClient, -}; \ No newline at end of file +}; diff --git a/src/util/buildInputData.js b/src/util/buildInputData.js deleted file mode 100644 index de254e8..0000000 --- a/src/util/buildInputData.js +++ /dev/null @@ -1,19 +0,0 @@ -const InputData = require("../InputData"); - -module.exports = (lookup, keyTranslationFormat) => { - let inputData = new InputData(lookup); - - const hasCustomParameters = Object.keys(lookup.customParameters ?? {}).length > 0; - - for (let key in keyTranslationFormat) { - inputData.add(key, keyTranslationFormat[key]); - } - - if (hasCustomParameters) { - for (let key in lookup.customParameters) { - inputData.addCustomParameter(key, lookup.customParameters[key]); - } - } - - return inputData.data; -}; diff --git a/src/util/buildInputData.ts b/src/util/buildInputData.ts new file mode 100644 index 0000000..b295daf --- /dev/null +++ b/src/util/buildInputData.ts @@ -0,0 +1,28 @@ +import InputData from "../InputData.js"; + +interface LookupLike { + customParameters?: Record; + [key: string]: any; +} + +export default function buildInputData( + lookup: LookupLike, + keyTranslationFormat: Record, +): Record { + const inputData = new InputData(lookup); + + const customParameters: Record = lookup.customParameters ?? {}; + const hasCustomParameters = Object.keys(customParameters).length > 0; + + for (const key in keyTranslationFormat) { + inputData.add(key, keyTranslationFormat[key]); + } + + if (hasCustomParameters) { + for (const key in customParameters) { + inputData.addCustomParameter(key, customParameters[key]); + } + } + + return inputData.data; +} diff --git a/src/util/buildSmartyResponse.js b/src/util/buildSmartyResponse.js deleted file mode 100644 index 3e80df5..0000000 --- a/src/util/buildSmartyResponse.js +++ /dev/null @@ -1,10 +0,0 @@ -const Response = require("../Response.js"); - -function buildSmartyResponse(response, error) { - if (response) return new Response(response.status, response.data, response.error, response.headers); - return new Response(undefined, undefined, error) -} - -module.exports = { - buildSmartyResponse -}; \ No newline at end of file diff --git a/src/util/buildSmartyResponse.ts b/src/util/buildSmartyResponse.ts new file mode 100644 index 0000000..b2f1e12 --- /dev/null +++ b/src/util/buildSmartyResponse.ts @@ -0,0 +1,14 @@ +import Response from "../Response.js"; + +interface AxiosLikeResponse { + status: number; + data?: object[] | object | string | null | undefined; + error?: any; + headers?: Record | undefined; +} + +export function buildSmartyResponse(response?: AxiosLikeResponse, error?: Error): Response { + if (response) + return new Response(response.status, response.data, response.error, response.headers); + return new Response(0, null, error); +} diff --git a/src/util/buildUsStreetInputData.js b/src/util/buildUsStreetInputData.ts similarity index 72% rename from src/util/buildUsStreetInputData.js rename to src/util/buildUsStreetInputData.ts index a122803..6e2f6b4 100644 --- a/src/util/buildUsStreetInputData.js +++ b/src/util/buildUsStreetInputData.ts @@ -1,7 +1,10 @@ -const buildInputData = require("./buildInputData"); -const keyTranslationFormat = require("./apiToSDKKeyMap").usStreet; +import buildInputData from "./buildInputData.js"; +import apiToSDKKeyMap from "./apiToSDKKeyMap.js"; +import Lookup from "../us_street/Lookup.js"; -module.exports = (lookup) => { +const keyTranslationFormat = apiToSDKKeyMap.usStreet; + +export default function buildUsStreetInputData(lookup: Lookup): Record { // Apply default match strategy and candidates logic per Go SDK behavior let effectiveMatch = lookup.match; let effectiveCandidates = lookup.maxCandidates; @@ -28,4 +31,4 @@ module.exports = (lookup) => { }); return buildInputData(effectiveLookup, keyTranslationFormat); -}; +} diff --git a/src/util/sendBatch.js b/src/util/sendBatch.js deleted file mode 100644 index a32ab63..0000000 --- a/src/util/sendBatch.js +++ /dev/null @@ -1,42 +0,0 @@ -const Request = require("../Request"); -const Errors = require("../Errors"); -const buildInputData = require("../util/buildInputData"); - -module.exports = (batch, sender, Result, keyTranslationFormat, customBuildInputData) => { - if (batch.isEmpty()) throw new Errors.BatchEmptyError; - - let request = new Request(); - - if (batch.length() === 1) request.parameters = generateRequestPayload(batch)[0]; - else request.payload = generateRequestPayload(batch); - - return new Promise((resolve, reject) => { - sender.send(request) - .then(response => { - if (response.error) reject(response.error); - - resolve(assignResultsToLookups(batch, response)); - }) - .catch(reject); - }); - - function generateRequestPayload(batch) { - return batch.lookups.map((lookup) => { - if (customBuildInputData) { - return customBuildInputData(lookup); - } - return buildInputData(lookup, keyTranslationFormat); - }); - } - - function assignResultsToLookups(batch, response) { - response.payload.map(rawResult => { - let result = new Result(rawResult); - let lookup = batch.getByIndex(result.inputIndex); - - lookup.result.push(result); - }); - - return batch; - } -}; diff --git a/src/util/sendBatch.ts b/src/util/sendBatch.ts new file mode 100644 index 0000000..ccac4ee --- /dev/null +++ b/src/util/sendBatch.ts @@ -0,0 +1,51 @@ +import Request from "../Request.js"; +import { BatchEmptyError } from "../Errors.js"; +import buildInputData from "./buildInputData.js"; +import Batch from "../Batch.js"; +import { Sender, Response } from "../types.js"; + +export default function sendBatch( + batch: Batch, + sender: Sender, + Result: new (data: any) => { inputIndex: number }, + keyTranslationFormat: Record | null, + customBuildInputData?: (lookup: any) => Record, +): Promise { + if (batch.isEmpty()) throw new BatchEmptyError(); + + const request = new Request(); + + if (batch.length() === 1) request.parameters = generateRequestPayload(batch)[0]; + else request.payload = generateRequestPayload(batch); + + return new Promise((resolve, reject) => { + sender + .send(request) + .then((response) => { + if (response.error) return reject(response.error); + + resolve(assignResultsToLookups(batch, response)); + }) + .catch(reject); + }); + + function generateRequestPayload(batch: Batch): Record[] { + return batch.lookups.map((lookup) => { + if (customBuildInputData) { + return customBuildInputData(lookup); + } + return buildInputData(lookup, keyTranslationFormat!); + }); + } + + function assignResultsToLookups(batch: Batch, response: Response): Batch { + (response.payload as Record[]).forEach((rawResult: Record) => { + const result = new Result(rawResult); + const lookup = batch.getByIndex(result.inputIndex); + + lookup.result.push(result); + }); + + return batch; + } +} diff --git a/tests/fixtures/MockSleeper.js b/tests/fixtures/MockSleeper.ts similarity index 50% rename from tests/fixtures/MockSleeper.js rename to tests/fixtures/MockSleeper.ts index c4aa527..221fed5 100644 --- a/tests/fixtures/MockSleeper.js +++ b/tests/fixtures/MockSleeper.ts @@ -1,10 +1,11 @@ -class MockSleeper { +export default class MockSleeper { + sleepDurations: number[]; + constructor() { this.sleepDurations = []; } - sleep(ms) { + + sleep(ms: number) { this.sleepDurations.push(ms); } } - -module.exports = MockSleeper; \ No newline at end of file diff --git a/tests/fixtures/mock_senders.js b/tests/fixtures/mock_senders.js deleted file mode 100644 index 861466c..0000000 --- a/tests/fixtures/mock_senders.js +++ /dev/null @@ -1,43 +0,0 @@ -const {buildSmartyResponse} = require("../../src/util/buildSmartyResponse.js"); -const Response = require("../../src/Response"); - -module.exports = { - MockSender: function () { - let request = { - payload: undefined, - parameters: undefined, - baseUrlParam: undefined, - }; - this.request = request; - - this.send = function (clientRequest) { - request.payload = clientRequest.payload; - request.parameters = clientRequest.parameters; - request.baseUrlParam = clientRequest.baseUrlParam; - } - }, - MockSenderWithResponse: function (expectedPayload, expectedError) { - this.send = function () { - return new Promise((resolve, reject) => { - resolve(new Response("", expectedPayload, expectedError)); - }); - } - }, - MockSenderWithStatusCodesAndHeaders: function (statusCodes, headers = undefined, error = undefined) { - this.statusCodes = statusCodes; - this.headers = headers; - this.error = error; - this.currentStatusCodeIndex = 0; - - this.send = function (request) { - let mockResponse = { - status: this.statusCodes[this.currentStatusCodeIndex], - headers: this.headers, - error: this.error, - }; - const response = buildSmartyResponse(mockResponse); - this.currentStatusCodeIndex += 1; - return response; - } - } -}; diff --git a/tests/fixtures/mock_senders.ts b/tests/fixtures/mock_senders.ts new file mode 100644 index 0000000..4ab6ed2 --- /dev/null +++ b/tests/fixtures/mock_senders.ts @@ -0,0 +1,67 @@ +import { buildSmartyResponse } from "../../src/util/buildSmartyResponse.js"; +import Response from "../../src/Response.js"; +import { Request as IRequest, Response as IResponse } from "../../src/types.js"; + +export class MockSender { + request: { + payload: string | object | null; + parameters: Record; + baseUrlParam: string; + }; + + constructor() { + this.request = { + payload: null, + parameters: {}, + baseUrlParam: "", + }; + } + + send(clientRequest: IRequest): Promise { + this.request.payload = clientRequest.payload; + this.request.parameters = clientRequest.parameters; + this.request.baseUrlParam = clientRequest.baseUrlParam; + return undefined as unknown as Promise; + } +} + +export class MockSenderWithResponse { + private expectedPayload: object[] | object | string | null; + private expectedError: Error | null; + + constructor(expectedPayload: object[] | object | string | null, expectedError?: Error | null) { + this.expectedPayload = expectedPayload; + this.expectedError = expectedError ?? null; + } + + send(): Promise { + return new Promise((resolve) => { + resolve(new Response(0, this.expectedPayload, this.expectedError)); + }); + } +} + +export class MockSenderWithStatusCodesAndHeaders { + statusCodes: number[]; + headers: Record | undefined; + error: string | undefined; + currentStatusCodeIndex: number; + + constructor(statusCodes: number[], headers?: Record, error?: string) { + this.statusCodes = statusCodes; + this.headers = headers; + this.error = error; + this.currentStatusCodeIndex = 0; + } + + send(_request: IRequest) { + const mockResponse = { + status: this.statusCodes[this.currentStatusCodeIndex], + headers: this.headers, + error: this.error, + }; + const response = buildSmartyResponse(mockResponse); + this.currentStatusCodeIndex += 1; + return response; + } +} diff --git a/tests/international_address_autocomplete/test_Client.js b/tests/international_address_autocomplete/test_Client.ts similarity index 68% rename from tests/international_address_autocomplete/test_Client.js rename to tests/international_address_autocomplete/test_Client.ts index 9db7bf7..20a86ab 100644 --- a/tests/international_address_autocomplete/test_Client.js +++ b/tests/international_address_autocomplete/test_Client.ts @@ -1,18 +1,16 @@ -const chai = require("chai"); -const expect = chai.expect; -const Client = require("../../src/international_address_autocomplete/Client"); -const Lookup = require("../../src/international_address_autocomplete/Lookup"); -const Suggestion = require("../../src/international_address_autocomplete/Suggestion"); -const errors = require("../../src/Errors"); -const MockSender = require("../fixtures/mock_senders").MockSender; -const MockSenderWithResponse = require("../fixtures/mock_senders").MockSenderWithResponse; +import { expect } from "chai"; +import Client from "../../src/international_address_autocomplete/Client.js"; +import Lookup from "../../src/international_address_autocomplete/Lookup.js"; +import Suggestion from "../../src/international_address_autocomplete/Suggestion.js"; +import errors from "../../src/Errors.js"; +import { MockSender, MockSenderWithResponse } from "../fixtures/mock_senders.js"; describe("An International Address Autocomplete Client", function () { it("correctly builds parameter", function () { let mockSender = new MockSender(); let client = new Client(mockSender); let search = "("; - let lookup = new Lookup({search}); + let lookup = new Lookup({ search }); let expectedParameters = { max_results: 5, search: "(", @@ -26,7 +24,7 @@ describe("An International Address Autocomplete Client", function () { let mockSender = new MockSender(); let client = new Client(mockSender); let search = "("; - let lookup = new Lookup({search}); + let lookup = new Lookup({ search }); lookup.search = search; lookup.country = "Russia"; let expectedParameters = { @@ -43,7 +41,7 @@ describe("An International Address Autocomplete Client", function () { let mockSender = new MockSender(); let client = new Client(mockSender); let search = "("; - let lookup = new Lookup({search}); + let lookup = new Lookup({ search }); lookup.search = search; lookup.maxResults = 10; let expectedParameters = { @@ -65,22 +63,22 @@ describe("An International Address Autocomplete Client", function () { const responseData = { candidates: [ { - "street": "L alleya", - "locality": "Novosibirsk", - "administrative_area": "Novosibirskaya oblast'", - "postal_code": "40000", - "country_iso3": "RUS", - } - ] + street: "L alleya", + locality: "Novosibirsk", + administrative_area: "Novosibirskaya oblast'", + postal_code: "40000", + country_iso3: "RUS", + }, + ], }; let mockSender = new MockSenderWithResponse(responseData); let client = new Client(mockSender); - let lookup = new Lookup({search: "f"}); + let lookup = new Lookup({ search: "f" }); let expectedSuggestion = new Suggestion(responseData.candidates[0]); return client.send(lookup).then(() => { expect(lookup.result[0]).to.deep.equal(expectedSuggestion); }); }); -}); \ No newline at end of file +}); diff --git a/tests/international_address_autocomplete/test_Lookup.js b/tests/international_address_autocomplete/test_Lookup.ts similarity index 73% rename from tests/international_address_autocomplete/test_Lookup.js rename to tests/international_address_autocomplete/test_Lookup.ts index 7d47618..54a64a9 100644 --- a/tests/international_address_autocomplete/test_Lookup.js +++ b/tests/international_address_autocomplete/test_Lookup.ts @@ -1,41 +1,40 @@ -const chai = require("chai"); -const expect = chai.expect; -const Lookup = require("../../src/international_address_autocomplete/Lookup"); +import { expect } from "chai"; +import Lookup from "../../src/international_address_autocomplete/Lookup.js"; describe("An International Address Autocomplete lookup", function () { it("Can be newed up with a prefix", function () { const expectedPrefix = "z"; - let lookup = new Lookup({search: expectedPrefix}); + let lookup = new Lookup({ search: expectedPrefix }); expect(lookup.search).to.equal(expectedPrefix); }); it("Set address ID", function () { const addressId = "111"; - let lookup = new Lookup({addressId}); + let lookup = new Lookup({ addressId }); expect(lookup.addressId).to.equal(addressId); }); it("Set country", function () { const country = "Russia"; - let lookup = new Lookup({country}); + let lookup = new Lookup({ country }); expect(lookup.country).to.equal(country); }); it("Set max results", function () { const maxResults = 10000; - let lookup = new Lookup({maxResults}); + let lookup = new Lookup({ maxResults }); expect(lookup.maxResults).to.equal(maxResults); }); it("Set include only include locality param", function () { const onlyIncludeLocality = "locality"; - let lookup = new Lookup({includeOnlyLocality: onlyIncludeLocality}); + let lookup = new Lookup({ includeOnlyLocality: onlyIncludeLocality }); expect(lookup.includeOnlyLocality).to.equal(onlyIncludeLocality); }); it("Set include only include postal code param", function () { const onlyIncludePostalCode = "post code"; - let lookup = new Lookup({includeOnlyPostalCode: onlyIncludePostalCode}); + let lookup = new Lookup({ includeOnlyPostalCode: onlyIncludePostalCode }); expect(lookup.includeOnlyPostalCode).to.equal(onlyIncludePostalCode); }); @@ -53,4 +52,4 @@ describe("An International Address Autocomplete lookup", function () { let lookup = new Lookup(); expect(lookup).to.deep.equal(defaultLookup); }); -}); \ No newline at end of file +}); diff --git a/tests/international_postal_code/test_Client.js b/tests/international_postal_code/test_Client.ts similarity index 75% rename from tests/international_postal_code/test_Client.js rename to tests/international_postal_code/test_Client.ts index 0d79d67..6137dfa 100644 --- a/tests/international_postal_code/test_Client.js +++ b/tests/international_postal_code/test_Client.ts @@ -1,23 +1,14 @@ -const chai = require("chai"); -const expect = chai.expect; -const Client = require("../../src/international_postal_code/Client"); -const Lookup = require("../../src/international_postal_code/Lookup"); -const MockSender = require("../fixtures/mock_senders").MockSender; -const MockSenderWithResponse = require("../fixtures/mock_senders").MockSenderWithResponse; +import { expect } from "chai"; +import Client from "../../src/international_postal_code/Client.js"; +import Lookup from "../../src/international_postal_code/Lookup.js"; +import { MockSender, MockSenderWithResponse } from "../fixtures/mock_senders.js"; describe("An International Postal Code client", function () { - it("has an inner sender.", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - - expect(client.sender).to.deep.equal(mockSender); - }); - it("throws an error if sending without a lookup.", function () { let mockSender = new MockSender(); let client = new Client(mockSender); - expect(() => client.send()).to.throw(); + expect(() => (client.send as any)()).to.throw(); }); it("attaches a result from a response to a lookup.", function () { diff --git a/tests/international_postal_code/test_Lookup.js b/tests/international_postal_code/test_Lookup.ts similarity index 78% rename from tests/international_postal_code/test_Lookup.js rename to tests/international_postal_code/test_Lookup.ts index 94367db..98a86ee 100644 --- a/tests/international_postal_code/test_Lookup.js +++ b/tests/international_postal_code/test_Lookup.ts @@ -1,6 +1,5 @@ -const chai = require("chai"); -const expect = chai.expect; -const Lookup = require("../../src/international_postal_code/Lookup"); +import { expect } from "chai"; +import Lookup from "../../src/international_postal_code/Lookup.js"; describe("An International Postal Code lookup", function () { it("correctly populates fields.", function () { @@ -19,6 +18,6 @@ describe("An International Postal Code lookup", function () { let lookup = new Lookup("Brazil", "02516-040"); lookup.addCustomParameter("test", "value"); - expect(lookup.customParameters.test).to.equal("value"); + expect(lookup.customParameters["test"]).to.equal("value"); }); }); diff --git a/tests/international_postal_code/test_Result.js b/tests/international_postal_code/test_Result.ts similarity index 85% rename from tests/international_postal_code/test_Result.js rename to tests/international_postal_code/test_Result.ts index bc873de..9f723d3 100644 --- a/tests/international_postal_code/test_Result.js +++ b/tests/international_postal_code/test_Result.ts @@ -1,6 +1,5 @@ -const chai = require("chai"); -const expect = chai.expect; -const Result = require("../../src/international_postal_code/Result"); +import { expect } from "chai"; +import Result from "../../src/international_postal_code/Result.js"; describe("An International Postal Code result", function () { it("populates with the appropriate fields.", function () { @@ -43,9 +42,9 @@ describe("An International Postal Code result", function () { const result = new Result(sampleResponse); - expect(result.inputId).to.equal(undefined); - expect(result.superAdministrativeArea).to.equal(undefined); - expect(result.postalCodeExtra).to.equal(undefined); + expect(result.inputId).to.equal(""); + expect(result.superAdministrativeArea).to.equal(""); + expect(result.postalCodeExtra).to.equal(""); expect(result.administrativeArea).to.equal("SP"); expect(result.locality).to.equal("São Paulo"); expect(result.postalCode).to.equal("02516-040"); diff --git a/tests/international_street/test_Candidate.js b/tests/international_street/test_Candidate.ts similarity index 98% rename from tests/international_street/test_Candidate.js rename to tests/international_street/test_Candidate.ts index 7e3b898..b550606 100644 --- a/tests/international_street/test_Candidate.js +++ b/tests/international_street/test_Candidate.ts @@ -1,6 +1,5 @@ -const chai = require("chai"); -const expect = chai.expect; -const Candidate = require("../../src/international_street/Candidate"); +import { expect } from "chai"; +import Candidate from "../../src/international_street/Candidate.js"; describe("An International match candidate", function () { it("populates with the appropriate fields.", function () { diff --git a/tests/international_street/test_Client.js b/tests/international_street/test_Client.ts similarity index 63% rename from tests/international_street/test_Client.js rename to tests/international_street/test_Client.ts index 20e64e7..96a51fc 100644 --- a/tests/international_street/test_Client.js +++ b/tests/international_street/test_Client.ts @@ -1,20 +1,11 @@ -const chai = require("chai"); -const expect = chai.expect; -const Client = require("../../src/international_street/Client"); -const Lookup = require("../../src/international_street/Lookup"); -const Candidate = require("../../src/international_street/Candidate"); -const errors = require("../../src/Errors"); -const MockSender = require("../fixtures/mock_senders").MockSender; -const MockSenderWithResponse = require("../fixtures/mock_senders").MockSenderWithResponse; +import { expect } from "chai"; +import Client from "../../src/international_street/Client.js"; +import Lookup from "../../src/international_street/Lookup.js"; +import Candidate from "../../src/international_street/Candidate.js"; +import errors from "../../src/Errors.js"; +import { MockSender, MockSenderWithResponse } from "../fixtures/mock_senders.js"; describe("An International Street client", function () { - it("has an inner sender.", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - - expect(client.sender).to.deep.equal(mockSender); - }); - it("throws an error if sending without a lookup.", function () { let mockSender = new MockSender(); let client = new Client(mockSender); @@ -57,13 +48,13 @@ describe("An International Street client", function () { }); it("attaches a match candidate from a response to a lookup.", function () { - const expectedMockPayload = [{address1: "A", }]; + const expectedMockPayload = [{ address1: "A" }]; let mockSender = new MockSenderWithResponse(expectedMockPayload); const client = new Client(mockSender); let lookup = new Lookup(); - let expectedResult = new Candidate({address1: "A"}); + let expectedResult = new Candidate({ address1: "A" }); - return client.send(lookup).then(response => { + return client.send(lookup).then((_response) => { expect(lookup.result[0]).to.deep.equal(expectedResult); }); }); diff --git a/tests/international_street/test_Lookup.js b/tests/international_street/test_Lookup.ts similarity index 84% rename from tests/international_street/test_Lookup.js rename to tests/international_street/test_Lookup.ts index ed4e40f..5b9f9d0 100644 --- a/tests/international_street/test_Lookup.js +++ b/tests/international_street/test_Lookup.ts @@ -1,15 +1,16 @@ -const chai = require("chai"); -const expect = chai.expect; -const Lookup = require("../../src/international_street/Lookup"); -const errors = require("../../src/Errors"); +import { expect } from "chai"; +import Lookup from "../../src/international_street/Lookup.js"; +import errors from "../../src/Errors.js"; describe("An International Street lookup", function () { const messages = { countryRequired: "Country field is required.", freeformOrAddress1Required: "Either freeform or address1 is required.", - insufficientInformation: "Insufficient information: One or more required fields were not set on the lookup.", + insufficientInformation: + "Insufficient information: One or more required fields were not set on the lookup.", badGeocode: "Invalid input: geocode can only be set to 'true' (default is 'false'.", - invalidLanguage: "Invalid input: language can only be set to 'latin' or 'native'. When not set, the the output language will match the language of the input values." + invalidLanguage: + "Invalid input: language can only be set to 'latin' or 'native'. When not set, the the output language will match the language of the input values.", }; it("correctly populates fields.", function () { @@ -93,16 +94,15 @@ describe("An International Street lookup", function () { expect(lookup2.ensureValidData()).to.equal(true); }); - function ensureValidationThrows(callback, message) { + function ensureValidationThrows(callback: any, message: any) { let expectedError = new errors.UnprocessableEntityError(message); try { callback(); expect(true).to.equal(false); - } - catch (error) { + } catch (error: any) { expect(error.message).to.equal(expectedError.message); expect(error).to.be.an.instanceOf(errors.UnprocessableEntityError); } } -}); \ No newline at end of file +}); diff --git a/tests/test_Batch.js b/tests/test_Batch.ts similarity index 64% rename from tests/test_Batch.js rename to tests/test_Batch.ts index 383cefb..212ec3b 100644 --- a/tests/test_Batch.js +++ b/tests/test_Batch.ts @@ -1,28 +1,27 @@ -const chai = require("chai"); -const expect = chai.expect; -const errors = require("../src/Errors"); -const Batch = require("../src/Batch"); -const Lookup = require("../src/us_street/Lookup"); +import { expect } from "chai"; +import errors from "../src/Errors.js"; +import Batch from "../src/Batch.js"; +import Lookup from "../src/us_street/Lookup.js"; describe("A batch", function () { - let batch; + let batch: any; beforeEach(function () { batch = new Batch(); }); - it ("has a lookups field.", function () { + it("has a lookups field.", function () { expect(batch.hasOwnProperty("lookups")).to.equal(true); expect(Array.isArray(batch.lookups)).to.equal(true); }); - it ("can add a lookup to its array of lookups.", function () { + it("can add a lookup to its array of lookups.", function () { expect(batch.lookups.length).to.equal(0); batch.add("Hi."); expect(batch.lookups.length).to.equal(1); }); - it ("errors if you add a lookup when it's full.", function () { + it("errors if you add a lookup when it's full.", function () { for (let i = 0; i < 100; i++) { let lookup = {}; batch.add(lookup); @@ -31,13 +30,13 @@ describe("A batch", function () { expect(() => batch.add({})).to.throw(errors.BatchFullError); }); - it ("can be cleared.", function () { + it("can be cleared.", function () { batch.add("Hi."); batch.clear(); expect(batch.lookups.length).to.equal(0); }); - it ("has a length.", function () { + it("has a length.", function () { expect(batch.length()).to.equal(0); for (let i = 0; i < 50; i++) { batch.add(i); @@ -45,7 +44,7 @@ describe("A batch", function () { expect(batch.length()).to.equal(50); }); - it ("returns a lookup by index.", function () { + it("returns a lookup by index.", function () { for (let i = 0; i < 100; i++) { batch.add(i); } @@ -53,10 +52,10 @@ describe("A batch", function () { expect(batch.getByIndex(50)).to.equal(50); }); - it ("returns a lookup by input id.", function () { + it("returns a lookup by input id.", function () { for (let i = 0; i < 100; i++) { let lookup = new Lookup(); - lookup.inputId = i; + lookup.inputId = i as any; batch.add(lookup); } @@ -65,9 +64,9 @@ describe("A batch", function () { expect(batch.getByInputId(50)).to.deep.equal(expectedLookup); }); - it ("knows if it's empty.", function () { + it("knows if it's empty.", function () { expect(batch.isEmpty()).to.equal(true); batch.add("1"); expect(batch.isEmpty()).to.equal(false); }); -}); \ No newline at end of file +}); diff --git a/tests/test_ExtractExample.ts b/tests/test_ExtractExample.ts index d747694..ae100af 100644 --- a/tests/test_ExtractExample.ts +++ b/tests/test_ExtractExample.ts @@ -1,5 +1,5 @@ import { expect } from "chai"; -import * as SmartySDK from "../dist/esm/index.mjs"; +import * as SmartySDK from "../index.js"; describe("Extract example test", () => { const authId = ""; diff --git a/tests/test_HttpSender.js b/tests/test_HttpSender.ts similarity index 68% rename from tests/test_HttpSender.js rename to tests/test_HttpSender.ts index f526fe2..e69cf3a 100644 --- a/tests/test_HttpSender.js +++ b/tests/test_HttpSender.ts @@ -1,10 +1,9 @@ -const chai = require("chai"); -const expect = chai.expect; -const Request = require("../src/Request"); -const HttpSender = require("../src/HttpSender"); -const {buildSmartyResponse} = require("../src/util/buildSmartyResponse"); +import { expect } from "chai"; +import Request from "../src/Request.js"; +import HttpSender from "../src/HttpSender.js"; +import { buildSmartyResponse } from "../src/util/buildSmartyResponse.js"; -describe ("An Axios implementation of a HTTP sender", function () { +describe("An Axios implementation of a HTTP sender", function () { it("adds a data payload to the HTTP request config.", function () { let expectedPayload = "test payload"; let request = new Request(expectedPayload); @@ -15,7 +14,7 @@ describe ("An Axios implementation of a HTTP sender", function () { expect(requestConfig.data).to.equal(expectedPayload); }); - it ("adds a POST method to the HTTP request config when appropriate.", function () { + it("adds a POST method to the HTTP request config when appropriate.", function () { let request = new Request("test payload"); let sender = new HttpSender(); let requestConfig = sender.buildRequestConfig(request); @@ -24,7 +23,7 @@ describe ("An Axios implementation of a HTTP sender", function () { expect(requestConfig.method).to.equal("POST"); }); - it ("adds a GET method to the HTTP request config when appropriate.", function () { + it("adds a GET method to the HTTP request config when appropriate.", function () { let request = new Request(); let sender = new HttpSender(); let requestConfig = sender.buildRequestConfig(request); @@ -33,7 +32,7 @@ describe ("An Axios implementation of a HTTP sender", function () { expect(requestConfig.method).to.equal("GET"); }); - it ("add a timeout to the HTTP request config.", function () { + it("add a timeout to the HTTP request config.", function () { let request = new Request("test payload"); let sender = new HttpSender(); let requestConfig = sender.buildRequestConfig(request); @@ -47,30 +46,28 @@ describe ("An Axios implementation of a HTTP sender", function () { expect(customTimeoutRequestConfig.timeout).to.equal(5); }); - it ("adds parameters to the HTTP request config.", function () { + it("adds parameters to the HTTP request config.", function () { let request = new Request(""); let sender = new HttpSender(); - request.parameters.test = "1"; + request.parameters["test"] = "1"; let requestConfig = sender.buildRequestConfig(request); expect(requestConfig.hasOwnProperty("params")).to.equal(true); expect(requestConfig.params).to.deep.equal(request.parameters); }); - it ("adds headers to the HTTP request config.", function () { + it("adds headers to the HTTP request config.", function () { let request = new Request(""); let sender = new HttpSender(); let requestConfig = sender.buildRequestConfig(request); - let version = require("../package.json").version; expect(requestConfig.hasOwnProperty("headers")).to.equal(true); - expect(requestConfig.headers["Content-Type"]).to.equal("application/json; charset=utf-8"); + expect(requestConfig.headers!["Content-Type"]).to.equal("application/json; charset=utf-8"); }); - it ("has a response with the right status code.", function () { - let sender = new HttpSender(); + it("has a response with the right status code.", function () { let mockResponse = { - status: 200 + status: 200, }; let smartyResponse = buildSmartyResponse(mockResponse); @@ -78,12 +75,11 @@ describe ("An Axios implementation of a HTTP sender", function () { expect(smartyResponse.statusCode).to.equal(200); }); - it ("has a response with a payload.", function () { - let sender = new HttpSender(); + it("has a response with a payload.", function () { let mockData = [1, 2, 3]; let mockResponse = { status: 200, - data: mockData + data: mockData, }; let smartyResponse = buildSmartyResponse(mockResponse); diff --git a/tests/test_LicenseSender.js b/tests/test_LicenseSender.ts similarity index 70% rename from tests/test_LicenseSender.js rename to tests/test_LicenseSender.ts index bbe7971..0494950 100644 --- a/tests/test_LicenseSender.js +++ b/tests/test_LicenseSender.ts @@ -1,17 +1,16 @@ -const chai = require("chai"); -const expect = chai.expect; -const LicenseSender = require("../src/LicenseSender"); -const Request = require("../src/Request"); +import { expect } from "chai"; +import LicenseSender from "../src/LicenseSender.js"; +import Request from "../src/Request.js"; describe("A license sender", function () { - let innerSender; - let request; - let licenses; - let licenseSender; + let innerSender: any; + let request: any; + let licenses: any; + let licenseSender: any; beforeEach(() => { innerSender = { - send: () => true + send: () => Promise.resolve(), }; request = new Request(); }); @@ -21,14 +20,14 @@ describe("A license sender", function () { licenseSender = new LicenseSender(innerSender, licenses); licenseSender.send(request); - expect(request.parameters).contains({"license": "0,1,2"}); + expect(request.parameters).contains({ license: "0,1,2" }); }); it("doesn't append license to query if array is empty.", function () { licenses = []; licenseSender = new LicenseSender(innerSender, licenses); licenseSender.send(request); - + expect(request.parameters).to.not.have.property("license"); }); diff --git a/tests/test_RetrySender.ts b/tests/test_RetrySender.ts index 731df8a..af93322 100644 --- a/tests/test_RetrySender.ts +++ b/tests/test_RetrySender.ts @@ -6,7 +6,7 @@ import Response from "../src/Response.js"; import type { Sender, Sleeper, MockSenderInstance, MockSleeperInstance } from "../src/types"; class CompatibleMockSender implements MockSenderInstance { - statusCodes: string[]; + statusCodes: number[]; headers?: Record | undefined; error?: string | undefined; currentStatusCodeIndex: number; @@ -15,13 +15,13 @@ class CompatibleMockSender implements MockSenderInstance { currentStatusCodeIndex: number; }; - constructor(statusCodes: string[], headers?: Record, error?: string) { + constructor(statusCodes: number[], headers?: Record, error?: string) { this.statusCodes = statusCodes; this.headers = headers; this.error = error; this.currentStatusCodeIndex = 0; this.mockSender = new (MockSenderWithStatusCodesAndHeaders as new ( - ...args: [string[], Record?, string?] + ...args: [number[], Record?, string?] ) => { send(request: Request): Response; currentStatusCodeIndex: number; @@ -52,53 +52,40 @@ async function sendWithRetry(retries: number, inner: Sender, sleeper: Sleeper) { describe("Retry Sender tests", function () { it("test success does not retry", async function () { - let inner = new CompatibleMockSender(["200"]); + let inner = new CompatibleMockSender([200]); await sendWithRetry(5, inner, new CompatibleMockSleeper()); expect(inner.currentStatusCodeIndex).to.equal(1); }); it("test client error does not retry", async function () { - let inner = new CompatibleMockSender(["422"]); + let inner = new CompatibleMockSender([422]); await sendWithRetry(5, inner, new CompatibleMockSleeper()); expect(inner.currentStatusCodeIndex).to.equal(1); }); it("test will retry until success", async function () { - let inner = new CompatibleMockSender(["500", "500", "500", "200", "500"]); + let inner = new CompatibleMockSender([500, 500, 500, 200, 500]); await sendWithRetry(10, inner, new CompatibleMockSleeper()); expect(inner.currentStatusCodeIndex).to.equal(4); }); it("test return response if retry limit exceeded", async function () { - let inner = new CompatibleMockSender(["500", "500", "500", "500", "500"]); + let inner = new CompatibleMockSender([500, 500, 500, 500, 500]); const sleeper = new CompatibleMockSleeper(); const response = await sendWithRetry(4, inner, sleeper); expect(response); expect(inner.currentStatusCodeIndex).to.equal(5); - expect(response.statusCode).to.equal("500"); + expect(response.statusCode).to.equal(500); expect(sleeper.sleepDurations).to.deep.equal([0, 1, 2, 3]); }); it("test backoff does not exceed max", async function () { let inner = new CompatibleMockSender([ - "500", - "500", - "500", - "500", - "500", - "500", - "500", - "500", - "500", - "500", - "500", - "500", - "500", - "200", + 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 200, ]); const sleeper = new CompatibleMockSleeper(); @@ -115,7 +102,7 @@ describe("Retry Sender tests", function () { }); it("test sleep on rate limit", async function () { - let inner = new CompatibleMockSender(["429", "200"]); + let inner = new CompatibleMockSender([429, 200]); const sleeper = new CompatibleMockSleeper(); await sendWithRetry(5, inner, sleeper); @@ -124,7 +111,7 @@ describe("Retry Sender tests", function () { }); it("test rate limit error return", async function () { - let inner = new CompatibleMockSender(["429"], { "Retry-After": 7 }); + let inner = new CompatibleMockSender([429], { "Retry-After": 7 }); const sleeper = new CompatibleMockSleeper(); await sendWithRetry(10, inner, sleeper); @@ -133,7 +120,7 @@ describe("Retry Sender tests", function () { }); it("test retry after invalid value", async function () { - let inner = new CompatibleMockSender(["429"], { "Retry-After": "a" }); + let inner = new CompatibleMockSender([429], { "Retry-After": "a" }); const sleeper = new CompatibleMockSleeper(); await sendWithRetry(10, inner, sleeper); @@ -142,7 +129,7 @@ describe("Retry Sender tests", function () { }); it("test retry error", async function () { - let inner = new CompatibleMockSender(["429"], undefined, "Big Bad"); + let inner = new CompatibleMockSender([429], undefined, "Big Bad"); const sleeper = new CompatibleMockSleeper(); const response = await sendWithRetry(10, inner, sleeper); diff --git a/tests/test_StatusCodeSender.js b/tests/test_StatusCodeSender.js deleted file mode 100644 index 4d5637b..0000000 --- a/tests/test_StatusCodeSender.js +++ /dev/null @@ -1,95 +0,0 @@ -const chai = require("chai"); -const expect = chai.expect; -const StatusCodeSender = require("../src/StatusCodeSender"); -const Response = require("../src/Response"); -const Request = require("../src/Request"); -const errors = require("../src/Errors"); - -describe("A status code sender", function () { - it("doesn't attach an error on a 200.", function () { - let mockSender = { - send: () => { - return new Promise((resolve, reject) => { - resolve(new Response(200)); - }); - } - }; - - let statusCodeSender = new StatusCodeSender(mockSender); - let request = new Request(); - - return statusCodeSender.send(request).then(response => { - expect(response.error === undefined).to.equal(true); - }); - }); - - it("gives a custom message for 400", function () { - const payload = { - errors: [ - {message: "custom message"} - ] - }; - return expectedErrorWithPayloadMessage(400, payload); - }) - - it("returns an error message if payload is undefined", function () { - return expectedDefaultError() - }) - - it("gives an Internal Server Error on a 500.", function () { - return expectedErrorForStatusCode(errors.InternalServerError, 500); - }); - - it("gives an Service Unavailable error on a 503.", function () { - return expectedErrorForStatusCode(errors.ServiceUnavailableError, 503); - }); - - it("gives an Gateway Timeout error on a 504.", function () { - return expectedErrorForStatusCode(errors.GatewayTimeoutError, 504); - }); -}); - -const expectedErrorWithPayloadMessage = (errorCode, payload) => { - let mockSender = generateMockSender(errorCode, payload); - let statusCodeSender = new StatusCodeSender(mockSender); - let request = new Request(); - - return statusCodeSender.send(request).then(() => { - }, error => { - expect(error.error).to.be.an.instanceOf(errors.DefaultError); - expect(error.error.message).to.be.equal(payload.errors[0].message); - }) -} - -const expectedDefaultError = () => { - let mockSender = generateMockSender(400); - let statusCodeSender = new StatusCodeSender(mockSender); - let request = new Request(); - - return statusCodeSender.send(request).then(() => { - }, error => { - expect(error.error).to.be.an.instanceOf(errors.DefaultError); - expect(error.error.message).to.be.equal("unexpected error"); - }) -} - -function expectedErrorForStatusCode(expectedError, errorCode) { - let mockSender = generateMockSender(errorCode); - let statusCodeSender = new StatusCodeSender(mockSender); - let request = new Request(); - - return statusCodeSender.send(request).then(() => { - }, error => { - expect(error.error).to.be.an.instanceOf(expectedError); - }) -} - -function generateMockSender(errorCode, payload) { - return { - send: () => { - return new Promise((resolve, reject) => { - reject(new Response(errorCode, payload)) - }); - } - }; -} diff --git a/tests/test_StatusCodeSender.ts b/tests/test_StatusCodeSender.ts new file mode 100644 index 0000000..d272a7e --- /dev/null +++ b/tests/test_StatusCodeSender.ts @@ -0,0 +1,98 @@ +import { expect } from "chai"; +import StatusCodeSender from "../src/StatusCodeSender.js"; +import Response from "../src/Response.js"; +import Request from "../src/Request.js"; +import errors from "../src/Errors.js"; + +describe("A status code sender", function () { + it("doesn't attach an error on a 200.", function () { + let mockSender = { + send: () => { + return new Promise((resolve, _reject) => { + resolve(new Response(200)); + }); + }, + }; + + let statusCodeSender = new StatusCodeSender(mockSender as any); + let request = new Request(); + + return statusCodeSender.send(request).then((response) => { + expect(response.error === null).to.equal(true); + }); + }); + + it("gives a custom message for 400", function () { + const payload = { + errors: [{ message: "custom message" }], + }; + return expectedErrorWithPayloadMessage(400, payload); + }); + + it("returns an error message if payload is undefined", function () { + return expectedDefaultError(); + }); + + it("gives an Internal Server Error on a 500.", function () { + return expectedErrorForStatusCode(errors.InternalServerError, 500); + }); + + it("gives an Service Unavailable error on a 503.", function () { + return expectedErrorForStatusCode(errors.ServiceUnavailableError, 503); + }); + + it("gives an Gateway Timeout error on a 504.", function () { + return expectedErrorForStatusCode(errors.GatewayTimeoutError, 504); + }); +}); + +const expectedErrorWithPayloadMessage = (errorCode: any, payload: any) => { + let mockSender = generateMockSender(errorCode, payload); + let statusCodeSender = new StatusCodeSender(mockSender as any); + let request = new Request(); + + return statusCodeSender.send(request).then( + () => {}, + (error) => { + expect(error.error).to.be.an.instanceOf(errors.DefaultError); + expect(error.error.message).to.be.equal(payload.errors[0].message); + }, + ); +}; + +const expectedDefaultError = () => { + let mockSender = generateMockSender(400); + let statusCodeSender = new StatusCodeSender(mockSender as any); + let request = new Request(); + + return statusCodeSender.send(request).then( + () => {}, + (error) => { + expect(error.error).to.be.an.instanceOf(errors.DefaultError); + expect(error.error.message).to.be.equal("unexpected error"); + }, + ); +}; + +function expectedErrorForStatusCode(expectedError: any, errorCode: any) { + let mockSender = generateMockSender(errorCode); + let statusCodeSender = new StatusCodeSender(mockSender as any); + let request = new Request(); + + return statusCodeSender.send(request).then( + () => {}, + (error) => { + expect(error.error).to.be.an.instanceOf(expectedError); + }, + ); +} + +function generateMockSender(errorCode: any, payload?: any) { + return { + send: () => { + return new Promise((_resolve, reject) => { + reject(new Response(errorCode, payload)); + }); + }, + }; +} diff --git a/tests/us_autocomplete_pro/test_Client.js b/tests/us_autocomplete_pro/test_Client.ts similarity index 77% rename from tests/us_autocomplete_pro/test_Client.js rename to tests/us_autocomplete_pro/test_Client.ts index fa9bfed..6af06f0 100644 --- a/tests/us_autocomplete_pro/test_Client.js +++ b/tests/us_autocomplete_pro/test_Client.ts @@ -1,11 +1,9 @@ -const chai = require("chai"); -const expect = chai.expect; -const Client = require("../../src/us_autocomplete_pro/Client"); -const Lookup = require("../../src/us_autocomplete_pro/Lookup"); -const Suggestion = require("../../src/us_autocomplete_pro/Suggestion"); -const errors = require("../../src/Errors"); -const MockSender = require("../fixtures/mock_senders").MockSender; -const MockSenderWithResponse = require("../fixtures/mock_senders").MockSenderWithResponse; +import { expect } from "chai"; +import Client from "../../src/us_autocomplete_pro/Client.js"; +import Lookup from "../../src/us_autocomplete_pro/Lookup.js"; +import Suggestion from "../../src/us_autocomplete_pro/Suggestion.js"; +import errors from "../../src/Errors.js"; +import { MockSender, MockSenderWithResponse } from "../fixtures/mock_senders.js"; describe("A US Autocomplete Pro Client", function () { it("correctly builds parameters for a prefix only lookup.", function () { @@ -35,7 +33,7 @@ describe("A US Autocomplete Pro Client", function () { let lookup = new Lookup(); lookup.search = "1"; lookup.selected = "2"; - lookup.maxResults = "3"; + lookup.maxResults = "3" as any; lookup.includeOnlyCities = ["a,b", "c,d"]; lookup.includeOnlyStates = ["e", "f"]; lookup.includeOnlyZIPCodes = ["g", "h"]; @@ -43,7 +41,7 @@ describe("A US Autocomplete Pro Client", function () { lookup.preferCities = ["k,l", "m,n"]; lookup.preferStates = ["o", "p"]; lookup.preferZIPCodes = ["q", "r"]; - lookup.preferRatio = "s"; + lookup.preferRatio = "s" as any; lookup.preferGeolocation = "t"; lookup.source = "all"; @@ -79,38 +77,40 @@ describe("A US Autocomplete Pro Client", function () { let client = new Client(mockSender); let lookup = new Lookup("¯\\_(ツ)_/¯"); - return client.send(lookup).catch((e) => {expect(e).to.equal(expectedError);}); + return client.send(lookup).catch((e) => { + expect(e).to.equal(expectedError); + }); }); it("returns an empty array when no suggestions are returned.", () => { - let mockExpectedPayload = {suggestions: null}; + let mockExpectedPayload = { suggestions: null }; let mockSender = new MockSenderWithResponse(mockExpectedPayload); let client = new Client(mockSender); let lookup = new Lookup("Please let this be easy to test."); - let expectedSuggestion = []; + let expectedSuggestion: any[] = []; - return client.send(lookup).then(response => { + return client.send(lookup).then((_response) => { expect(lookup.result).to.deep.equal(expectedSuggestion); }); }); it("attaches suggestions from a response to a lookup.", function () { const responseData = { - streetLine: "a", + street_line: "a", secondary: "b", city: "c", state: "d", zipcode: "e", - entries: "f", + entries: 6, }; - let mockExpectedPayload = {suggestions: [responseData]}; + let mockExpectedPayload = { suggestions: [responseData] }; let mockSender = new MockSenderWithResponse(mockExpectedPayload); let client = new Client(mockSender); let lookup = new Lookup("Trevor the Vampire"); let expectedSuggestion = new Suggestion(responseData); - return client.send(lookup).then(response => { + return client.send(lookup).then((_response) => { expect(lookup.result[0]).to.deep.equal(expectedSuggestion); }); - }) + }); }); diff --git a/tests/us_autocomplete_pro/test_Lookup.js b/tests/us_autocomplete_pro/test_Lookup.ts similarity index 65% rename from tests/us_autocomplete_pro/test_Lookup.js rename to tests/us_autocomplete_pro/test_Lookup.ts index 0c5a084..79dc27b 100644 --- a/tests/us_autocomplete_pro/test_Lookup.js +++ b/tests/us_autocomplete_pro/test_Lookup.ts @@ -1,6 +1,5 @@ -const chai = require("chai"); -const expect = chai.expect; -const Lookup = require("../../src/us_autocomplete_pro/Lookup"); +import { expect } from "chai"; +import Lookup from "../../src/us_autocomplete_pro/Lookup.js"; describe("A US Autocomplete Pro Lookup", function () { it("can be newed up with a prefix.", function () { @@ -8,4 +7,4 @@ describe("A US Autocomplete Pro Lookup", function () { let lookup = new Lookup(expectedSearch); expect(lookup.search).to.equal(expectedSearch); }); -}); \ No newline at end of file +}); diff --git a/tests/us_autocomplete_pro/test_Suggestion.js b/tests/us_autocomplete_pro/test_Suggestion.ts similarity index 73% rename from tests/us_autocomplete_pro/test_Suggestion.js rename to tests/us_autocomplete_pro/test_Suggestion.ts index 872484d..009aea7 100644 --- a/tests/us_autocomplete_pro/test_Suggestion.js +++ b/tests/us_autocomplete_pro/test_Suggestion.ts @@ -1,6 +1,5 @@ -const chai = require("chai"); -const expect = chai.expect; -const Suggestion = require("../../src/us_autocomplete_pro/Suggestion"); +import { expect } from "chai"; +import Suggestion from "../../src/us_autocomplete_pro/Suggestion.js"; describe("A US Autocomplete Pro Suggestion", function () { it("is initialized correctly with API response data.", function () { @@ -10,7 +9,7 @@ describe("A US Autocomplete Pro Suggestion", function () { city: "c", state: "d", zipcode: "e", - entries: "f", + entries: 6, }; let suggestion = new Suggestion(mockSuggestion); @@ -19,6 +18,6 @@ describe("A US Autocomplete Pro Suggestion", function () { expect(suggestion.city).to.equal("c"); expect(suggestion.state).to.equal("d"); expect(suggestion.zipcode).to.equal("e"); - expect(suggestion.entries).to.equal("f"); + expect(suggestion.entries).to.equal(6); }); -}); \ No newline at end of file +}); diff --git a/tests/us_enrichment/test_Client.js b/tests/us_enrichment/test_Client.js deleted file mode 100644 index 27cc556..0000000 --- a/tests/us_enrichment/test_Client.js +++ /dev/null @@ -1,455 +0,0 @@ -const chai = require("chai"); -const expect = chai.expect; -const Client = require("../../src/us_enrichment/Client"); -const Lookup = require("../../src/us_enrichment/Lookup"); -const errors = require("../../src/Errors"); -const MockSender = require("../fixtures/mock_senders").MockSender; -const MockSenderWithResponse = require("../fixtures/mock_senders").MockSenderWithResponse; -const {Response, FinancialResponse, GeoResponse} = require("../../src/us_enrichment/Response"); - -describe("A US Enrichment Client", function () { - it("composes principal url path properly", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - let smartyKey = "0"; - let lookup = new Lookup(smartyKey); - - client.sendPrincipal(lookup); - - expect(mockSender.request.baseUrlParam).to.deep.equal("0/property/principal"); - }) - - it("composes financial url path properly", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - let smartyKey = "0"; - let lookup = new Lookup(smartyKey); - - client.sendFinancial(lookup); - - expect(mockSender.request.baseUrlParam).to.deep.equal("0/property/financial"); - }) - - it("composes geo url path properly", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - let smartyKey = "0"; - let lookup = new Lookup(smartyKey); - - client.sendGeo(lookup); - - expect(mockSender.request.baseUrlParam).to.deep.equal("0/geo-reference"); - }) - - it("composes secondary url path properly", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - let smartyKey = "0"; - let lookup = new Lookup(smartyKey); - - client.sendSecondary(lookup); - - expect(mockSender.request.baseUrlParam).to.deep.equal("0/secondary"); - }) - - it("composes secondary count url path properly", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - let smartyKey = "0"; - let lookup = new Lookup(smartyKey); - - client.sendSecondaryCount(lookup); - - expect(mockSender.request.baseUrlParam).to.deep.equal("0/secondary/count"); - }) - - it("correctly builds parameters for a smartyKey only principal lookup.", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - let smartyKey = '(>")>#'; - let include = "1"; - let lookup = new Lookup(smartyKey, include); - let expectedParameters = { - include: include, - }; - - client.sendPrincipal(lookup); - - expect(mockSender.request.parameters).to.deep.equal(expectedParameters); - }); - - it("correctly builds parameters for a smartyKey only financial lookup.", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - let smartyKey = '(>")>#'; - let include = "1"; - let lookup = new Lookup(smartyKey, include); - let expectedParameters = { - include: include, - }; - - client.sendFinancial(lookup); - - expect(mockSender.request.parameters).to.deep.equal(expectedParameters); - }); - - it("correctly builds parameters for a smartyKey only geo lookup.", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - let smartyKey = '(>")>#'; - let include = "1"; - let lookup = new Lookup(smartyKey, include); - let expectedParameters = { - include: include, - }; - - client.sendGeo(lookup); - - expect(mockSender.request.parameters).to.deep.equal(expectedParameters); - }); - - it("correctly builds parameters for a smartyKey only secondary lookup.", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - let smartyKey = '(>")>#'; - let include = "1"; - let lookup = new Lookup(smartyKey, include); - let expectedParameters = { - include: include, - }; - - client.sendSecondary(lookup); - - expect(mockSender.request.parameters).to.deep.equal(expectedParameters); - }); - - it("correctly builds parameters for a smartyKey only secondary count lookup.", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - let smartyKey = '(>")>#'; - let include = "1"; - let lookup = new Lookup(smartyKey, include); - let expectedParameters = { - include: include, - }; - - client.sendSecondaryCount(lookup); - - expect(mockSender.request.parameters).to.deep.equal(expectedParameters); - }); - - it("correctly builds parameters for a fully-populated principal lookup.", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - let lookup = new Lookup("0", "1", "2", "3", "4"); - - let expectedParameters = { - include: "1", - exclude: "2", - dataset: "3", - data_subset: "4", - }; - - client.sendPrincipal(lookup); - expect(mockSender.request.parameters).to.deep.equal(expectedParameters); - }); - - it("correctly builds parameters for a fully-populated financial lookup.", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - let lookup = new Lookup("0", "1", "2", "3", "4"); - - let expectedParameters = { - include: "1", - exclude: "2", - dataset: "3", - data_subset: "4", - }; - - client.sendFinancial(lookup); - expect(mockSender.request.parameters).to.deep.equal(expectedParameters); - }); - - it("correctly builds parameters for a fully-populated geo lookup.", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - let lookup = new Lookup("0", "1", "2", "3", "4"); - - let expectedParameters = { - include: "1", - exclude: "2", - dataset: "3", - data_subset: "4", - }; - - client.sendGeo(lookup); - expect(mockSender.request.parameters).to.deep.equal(expectedParameters); - }); - - it("correctly builds parameters for a fully-populated secondary lookup.", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - let lookup = new Lookup("0", "1", "2", "3", "4"); - - let expectedParameters = { - include: "1", - exclude: "2", - dataset: "3", - data_subset: "4", - }; - - client.sendSecondary(lookup); - expect(mockSender.request.parameters).to.deep.equal(expectedParameters); - }); - - it("correctly builds parameters for a fully-populated secondary count lookup.", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - let lookup = new Lookup("0", "1", "2", "3", "4"); - - let expectedParameters = { - include: "1", - exclude: "2", - dataset: "3", - data_subset: "4", - }; - - client.sendSecondaryCount(lookup); - expect(mockSender.request.parameters).to.deep.equal(expectedParameters); - }); - - it("throws an error if sending without a principal lookup.", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - expect(client.sendPrincipal).to.throw(errors.UndefinedLookupError); - }); - - it("throws an error if sending without a financial lookup.", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - expect(client.sendFinancial).to.throw(errors.UndefinedLookupError); - }); - - it("throws an error if sending without a geo lookup.", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - expect(client.sendGeo).to.throw(errors.UndefinedLookupError); - }); - - it("throws an error if sending without a secondary lookup.", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - expect(client.sendSecondary).to.throw(errors.UndefinedLookupError); - }); - - it("throws an error if sending without a secondary count lookup.", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - expect(client.sendSecondaryCount).to.throw(errors.UndefinedLookupError); - }); - - it("rejects with an exception if the principal response comes back with an error.", function () { - let expectedError = new Error("I'm the error."); - let mockSender = new MockSenderWithResponse("", expectedError); - let client = new Client(mockSender); - let lookup = new Lookup("¯\\_(ツ)_/¯"); - - return client.sendPrincipal(lookup).catch((e) => { - expect(e).to.equal(expectedError); - }); - }); - - it("rejects with an exception if the financial response comes back with an error.", function () { - let expectedError = new Error("I'm the error."); - let mockSender = new MockSenderWithResponse("", expectedError); - let client = new Client(mockSender); - let lookup = new Lookup("¯\\_(ツ)_/¯"); - - return client.sendFinancial(lookup).catch((e) => { - expect(e).to.equal(expectedError); - }); - }); - - it("rejects with an exception if the geo response comes back with an error.", function () { - let expectedError = new Error("I'm the error."); - let mockSender = new MockSenderWithResponse("", expectedError); - let client = new Client(mockSender); - let lookup = new Lookup("¯\\_(ツ)_/¯"); - - return client.sendGeo(lookup).catch((e) => { - expect(e).to.equal(expectedError); - }); - }); - - it("rejects with an exception if the secondary response comes back with an error.", function () { - let expectedError = new Error("I'm the error."); - let mockSender = new MockSenderWithResponse("", expectedError); - let client = new Client(mockSender); - let lookup = new Lookup("¯\\_(ツ)_/¯"); - - return client.sendSecondary(lookup).catch((e) => { - expect(e).to.equal(expectedError); - }); - }); - - it("rejects with an exception if the secondary count response comes back with an error.", function () { - let expectedError = new Error("I'm the error."); - let mockSender = new MockSenderWithResponse("", expectedError); - let client = new Client(mockSender); - let lookup = new Lookup("¯\\_(ツ)_/¯"); - - return client.sendSecondaryCount(lookup).catch((e) => { - expect(e).to.equal(expectedError); - }); - }); - - it("returns an empty array when no principal respo are returned.", () => { - let mockSender = new MockSenderWithResponse({}); - let client = new Client(mockSender); - let lookup = new Lookup("smartyKey"); - - return client.sendPrincipal(lookup).then(response => { - expect(lookup.response).to.deep.equal({}); - }); - }); - - it("returns an empty array when no financial suggestions are returned.", () => { - let mockSender = new MockSenderWithResponse({}); - let client = new Client(mockSender); - let lookup = new Lookup("smartyKey"); - - return client.sendFinancial(lookup).then(response => { - expect(lookup.response).to.deep.equal({}); - }); - }); - - it("returns an empty array when no geo suggestions are returned.", () => { - let mockSender = new MockSenderWithResponse({}); - let client = new Client(mockSender); - let lookup = new Lookup("smartyKey"); - - return client.sendGeo(lookup).then(response => { - expect(lookup.response).to.deep.equal({}); - }); - }); - - it("returns an empty array when no secondary suggestions are returned.", () => { - let mockSender = new MockSenderWithResponse({}); - let client = new Client(mockSender); - let lookup = new Lookup("smartyKey"); - - return client.sendSecondary(lookup).then(response => { - expect(lookup.response).to.deep.equal({}); - }); - }); - - it("returns an empty array when no secondary count suggestions are returned.", () => { - let mockSender = new MockSenderWithResponse({}); - let client = new Client(mockSender); - let lookup = new Lookup("smartyKey"); - - return client.sendSecondaryCount(lookup).then(response => { - expect(lookup.response).to.deep.equal({}); - }); - }); - - it("attaches response to a principal lookup.", function () { - const rawMockResponse = { - smarty_key: "a", - data_set_name: "b", - data_subset_name: "c", - attributes: { - assessed_improvement_percent: "1" - }, - }; - let mockResponse = new Response(rawMockResponse); - - let mockSender = new MockSenderWithResponse(mockResponse); - let client = new Client(mockSender); - let lookup = new Lookup("smartyKey"); - - return client.sendPrincipal(lookup).then(response => { - expect(lookup.response).to.deep.equal(mockResponse); - }); - }) - - it("attaches response to a financial lookup.", function () { - const rawMockResponse = { - smarty_key: "a", - data_set_name: "b", - data_subset_name: "c", - attributes: { - assessed_improvement_percent: "1" - }, - }; - let mockResponse = new FinancialResponse(rawMockResponse); - - let mockSender = new MockSenderWithResponse(mockResponse); - let client = new Client(mockSender); - let lookup = new Lookup("smartyKey"); - - return client.sendFinancial(lookup).then(response => { - expect(lookup.response).to.deep.equal(mockResponse); - }); - }) - - it("attaches response to a geo lookup.", function () { - const rawMockResponse = { - smarty_key: "a", - data_set_name: "b", - data_subset_name: "c", - attributes: { - assessed_improvement_percent: "1" - }, - }; - let mockResponse = new GeoResponse(rawMockResponse); - - let mockSender = new MockSenderWithResponse(mockResponse); - let client = new Client(mockSender); - let lookup = new Lookup("smartyKey"); - - return client.sendGeo(lookup).then(response => { - expect(lookup.response).to.deep.equal(mockResponse); - }); - }) - - it("attaches response to a secondary lookup.", function () { - const rawMockResponse = { - smarty_key: "a", - data_set_name: "b", - data_subset_name: "c", - attributes: { - assessed_improvement_percent: "1" - }, - }; - let mockResponse = new Response(rawMockResponse); - - let mockSender = new MockSenderWithResponse(mockResponse); - let client = new Client(mockSender); - let lookup = new Lookup("smartyKey"); - - return client.sendSecondary(lookup).then(response => { - expect(lookup.response).to.deep.equal(mockResponse); - }); - }) - - it("attaches response to a secondary count lookup.", function () { - const rawMockResponse = { - smarty_key: "a", - data_set_name: "b", - data_subset_name: "c", - attributes: { - assessed_improvement_percent: "1" - }, - }; - let mockResponse = new Response(rawMockResponse); - - let mockSender = new MockSenderWithResponse(mockResponse); - let client = new Client(mockSender); - let lookup = new Lookup("smartyKey"); - - return client.sendSecondaryCount(lookup).then(response => { - expect(lookup.response).to.deep.equal(mockResponse); - }); - }) -}); diff --git a/tests/us_enrichment/test_Client.ts b/tests/us_enrichment/test_Client.ts new file mode 100644 index 0000000..95a0958 --- /dev/null +++ b/tests/us_enrichment/test_Client.ts @@ -0,0 +1,455 @@ +import { expect } from "chai"; +import Client from "../../src/us_enrichment/Client.js"; +import Lookup from "../../src/us_enrichment/Lookup.js"; +import errors from "../../src/Errors.js"; +import { MockSender, MockSenderWithResponse } from "../fixtures/mock_senders.js"; +import { Response, FinancialResponse, GeoResponse } from "../../src/us_enrichment/Response.js"; + +describe("A US Enrichment Client", function () { + it("composes principal url path properly", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + let smartyKey = "0"; + let lookup = new Lookup(smartyKey); + + client.sendPrincipal(lookup); + + expect(mockSender.request.baseUrlParam).to.deep.equal("0/property/principal"); + }); + + it("composes financial url path properly", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + let smartyKey = "0"; + let lookup = new Lookup(smartyKey); + + client.sendFinancial(lookup); + + expect(mockSender.request.baseUrlParam).to.deep.equal("0/property/financial"); + }); + + it("composes geo url path properly", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + let smartyKey = "0"; + let lookup = new Lookup(smartyKey); + + client.sendGeo(lookup); + + expect(mockSender.request.baseUrlParam).to.deep.equal("0/geo-reference"); + }); + + it("composes secondary url path properly", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + let smartyKey = "0"; + let lookup = new Lookup(smartyKey); + + client.sendSecondary(lookup); + + expect(mockSender.request.baseUrlParam).to.deep.equal("0/secondary"); + }); + + it("composes secondary count url path properly", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + let smartyKey = "0"; + let lookup = new Lookup(smartyKey); + + client.sendSecondaryCount(lookup); + + expect(mockSender.request.baseUrlParam).to.deep.equal("0/secondary/count"); + }); + + it("correctly builds parameters for a smartyKey only principal lookup.", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + let smartyKey = '(>")>#'; + let include = "1"; + let lookup = new Lookup(smartyKey, include); + let expectedParameters = { + include: include, + }; + + client.sendPrincipal(lookup); + + expect(mockSender.request.parameters).to.deep.equal(expectedParameters); + }); + + it("correctly builds parameters for a smartyKey only financial lookup.", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + let smartyKey = '(>")>#'; + let include = "1"; + let lookup = new Lookup(smartyKey, include); + let expectedParameters = { + include: include, + }; + + client.sendFinancial(lookup); + + expect(mockSender.request.parameters).to.deep.equal(expectedParameters); + }); + + it("correctly builds parameters for a smartyKey only geo lookup.", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + let smartyKey = '(>")>#'; + let include = "1"; + let lookup = new Lookup(smartyKey, include); + let expectedParameters = { + include: include, + }; + + client.sendGeo(lookup); + + expect(mockSender.request.parameters).to.deep.equal(expectedParameters); + }); + + it("correctly builds parameters for a smartyKey only secondary lookup.", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + let smartyKey = '(>")>#'; + let include = "1"; + let lookup = new Lookup(smartyKey, include); + let expectedParameters = { + include: include, + }; + + client.sendSecondary(lookup); + + expect(mockSender.request.parameters).to.deep.equal(expectedParameters); + }); + + it("correctly builds parameters for a smartyKey only secondary count lookup.", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + let smartyKey = '(>")>#'; + let include = "1"; + let lookup = new Lookup(smartyKey, include); + let expectedParameters = { + include: include, + }; + + client.sendSecondaryCount(lookup); + + expect(mockSender.request.parameters).to.deep.equal(expectedParameters); + }); + + it("correctly builds parameters for a fully-populated principal lookup.", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + let lookup = new Lookup("0", "1", "2", "3", "4"); + + let expectedParameters = { + include: "1", + exclude: "2", + dataset: "3", + data_subset: "4", + }; + + client.sendPrincipal(lookup); + expect(mockSender.request.parameters).to.deep.equal(expectedParameters); + }); + + it("correctly builds parameters for a fully-populated financial lookup.", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + let lookup = new Lookup("0", "1", "2", "3", "4"); + + let expectedParameters = { + include: "1", + exclude: "2", + dataset: "3", + data_subset: "4", + }; + + client.sendFinancial(lookup); + expect(mockSender.request.parameters).to.deep.equal(expectedParameters); + }); + + it("correctly builds parameters for a fully-populated geo lookup.", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + let lookup = new Lookup("0", "1", "2", "3", "4"); + + let expectedParameters = { + include: "1", + exclude: "2", + dataset: "3", + data_subset: "4", + }; + + client.sendGeo(lookup); + expect(mockSender.request.parameters).to.deep.equal(expectedParameters); + }); + + it("correctly builds parameters for a fully-populated secondary lookup.", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + let lookup = new Lookup("0", "1", "2", "3", "4"); + + let expectedParameters = { + include: "1", + exclude: "2", + dataset: "3", + data_subset: "4", + }; + + client.sendSecondary(lookup); + expect(mockSender.request.parameters).to.deep.equal(expectedParameters); + }); + + it("correctly builds parameters for a fully-populated secondary count lookup.", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + let lookup = new Lookup("0", "1", "2", "3", "4"); + + let expectedParameters = { + include: "1", + exclude: "2", + dataset: "3", + data_subset: "4", + }; + + client.sendSecondaryCount(lookup); + expect(mockSender.request.parameters).to.deep.equal(expectedParameters); + }); + + it("throws an error if sending without a principal lookup.", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + expect(client.sendPrincipal).to.throw(errors.UndefinedLookupError); + }); + + it("throws an error if sending without a financial lookup.", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + expect(client.sendFinancial).to.throw(errors.UndefinedLookupError); + }); + + it("throws an error if sending without a geo lookup.", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + expect(client.sendGeo).to.throw(errors.UndefinedLookupError); + }); + + it("throws an error if sending without a secondary lookup.", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + expect(client.sendSecondary).to.throw(errors.UndefinedLookupError); + }); + + it("throws an error if sending without a secondary count lookup.", function () { + let mockSender = new MockSender(); + let client = new Client(mockSender); + expect(client.sendSecondaryCount).to.throw(errors.UndefinedLookupError); + }); + + it("rejects with an exception if the principal response comes back with an error.", function () { + let expectedError = new Error("I'm the error."); + let mockSender = new MockSenderWithResponse("", expectedError); + let client = new Client(mockSender); + let lookup = new Lookup("¯\\_(ツ)_/¯"); + + return client.sendPrincipal(lookup).catch((e) => { + expect(e).to.equal(expectedError); + }); + }); + + it("rejects with an exception if the financial response comes back with an error.", function () { + let expectedError = new Error("I'm the error."); + let mockSender = new MockSenderWithResponse("", expectedError); + let client = new Client(mockSender); + let lookup = new Lookup("¯\\_(ツ)_/¯"); + + return client.sendFinancial(lookup).catch((e) => { + expect(e).to.equal(expectedError); + }); + }); + + it("rejects with an exception if the geo response comes back with an error.", function () { + let expectedError = new Error("I'm the error."); + let mockSender = new MockSenderWithResponse("", expectedError); + let client = new Client(mockSender); + let lookup = new Lookup("¯\\_(ツ)_/¯"); + + return client.sendGeo(lookup).catch((e) => { + expect(e).to.equal(expectedError); + }); + }); + + it("rejects with an exception if the secondary response comes back with an error.", function () { + let expectedError = new Error("I'm the error."); + let mockSender = new MockSenderWithResponse("", expectedError); + let client = new Client(mockSender); + let lookup = new Lookup("¯\\_(ツ)_/¯"); + + return client.sendSecondary(lookup).catch((e) => { + expect(e).to.equal(expectedError); + }); + }); + + it("rejects with an exception if the secondary count response comes back with an error.", function () { + let expectedError = new Error("I'm the error."); + let mockSender = new MockSenderWithResponse("", expectedError); + let client = new Client(mockSender); + let lookup = new Lookup("¯\\_(ツ)_/¯"); + + return client.sendSecondaryCount(lookup).catch((e) => { + expect(e).to.equal(expectedError); + }); + }); + + it("returns an empty response when no principal data is returned.", () => { + let mockSender = new MockSenderWithResponse({}); + let client = new Client(mockSender); + let lookup = new Lookup("smartyKey"); + + return client.sendPrincipal(lookup).then((_response) => { + expect(lookup.response).to.deep.equal(new Response({})); + }); + }); + + it("returns an empty response when no financial data is returned.", () => { + let mockSender = new MockSenderWithResponse({}); + let client = new Client(mockSender); + let lookup = new Lookup("smartyKey"); + + return client.sendFinancial(lookup).then((_response) => { + expect(lookup.response).to.deep.equal(new FinancialResponse({})); + }); + }); + + it("returns an empty response when no geo data is returned.", () => { + let mockSender = new MockSenderWithResponse({}); + let client = new Client(mockSender); + let lookup = new Lookup("smartyKey"); + + return client.sendGeo(lookup).then((_response) => { + expect(lookup.response).to.deep.equal(new GeoResponse({})); + }); + }); + + it("returns an empty response when no secondary data is returned.", () => { + let mockSender = new MockSenderWithResponse({}); + let client = new Client(mockSender); + let lookup = new Lookup("smartyKey"); + + return client.sendSecondary(lookup).then((_response) => { + expect(lookup.response).to.deep.equal(new Response({})); + }); + }); + + it("returns an empty response when no secondary count data is returned.", () => { + let mockSender = new MockSenderWithResponse({}); + let client = new Client(mockSender); + let lookup = new Lookup("smartyKey"); + + return client.sendSecondaryCount(lookup).then((_response) => { + expect(lookup.response).to.deep.equal(new Response({})); + }); + }); + + it("attaches response to a principal lookup.", function () { + const rawMockPayload = { + smarty_key: "a", + data_set_name: "b", + data_subset_name: "c", + attributes: { + assessed_improvement_percent: "1", + }, + }; + let expectedResponse = new Response(rawMockPayload); + + let mockSender = new MockSenderWithResponse(rawMockPayload); + let client = new Client(mockSender); + let lookup = new Lookup("smartyKey"); + + return client.sendPrincipal(lookup).then((_response) => { + expect(lookup.response).to.deep.equal(expectedResponse); + }); + }); + + it("attaches response to a financial lookup.", function () { + const rawMockPayload = { + smarty_key: "a", + data_set_name: "b", + data_subset_name: "c", + attributes: { + assessed_improvement_percent: "1", + }, + }; + let expectedResponse = new FinancialResponse(rawMockPayload); + + let mockSender = new MockSenderWithResponse(rawMockPayload); + let client = new Client(mockSender); + let lookup = new Lookup("smartyKey"); + + return client.sendFinancial(lookup).then((_response) => { + expect(lookup.response).to.deep.equal(expectedResponse); + }); + }); + + it("attaches response to a geo lookup.", function () { + const rawMockPayload = { + smarty_key: "a", + data_set_name: "b", + attributes: { + census_block: { + accuracy: "high", + geoid: "12345", + }, + }, + }; + let expectedResponse = new GeoResponse(rawMockPayload); + + let mockSender = new MockSenderWithResponse(rawMockPayload); + let client = new Client(mockSender); + let lookup = new Lookup("smartyKey"); + + return client.sendGeo(lookup).then((_response) => { + expect(lookup.response).to.deep.equal(expectedResponse); + }); + }); + + it("attaches response to a secondary lookup.", function () { + const rawMockPayload = { + smarty_key: "a", + data_set_name: "b", + data_subset_name: "c", + attributes: { + assessed_improvement_percent: "1", + }, + }; + let expectedResponse = new Response(rawMockPayload); + + let mockSender = new MockSenderWithResponse(rawMockPayload); + let client = new Client(mockSender); + let lookup = new Lookup("smartyKey"); + + return client.sendSecondary(lookup).then((_response) => { + expect(lookup.response).to.deep.equal(expectedResponse); + }); + }); + + it("attaches response to a secondary count lookup.", function () { + const rawMockPayload = { + smarty_key: "a", + data_set_name: "b", + data_subset_name: "c", + attributes: { + assessed_improvement_percent: "1", + }, + }; + let expectedResponse = new Response(rawMockPayload); + + let mockSender = new MockSenderWithResponse(rawMockPayload); + let client = new Client(mockSender); + let lookup = new Lookup("smartyKey"); + + return client.sendSecondaryCount(lookup).then((_response) => { + expect(lookup.response).to.deep.equal(expectedResponse); + }); + }); +}); diff --git a/tests/us_enrichment/test_Lookup.js b/tests/us_enrichment/test_Lookup.ts similarity index 87% rename from tests/us_enrichment/test_Lookup.js rename to tests/us_enrichment/test_Lookup.ts index 419c944..2188d1e 100644 --- a/tests/us_enrichment/test_Lookup.js +++ b/tests/us_enrichment/test_Lookup.ts @@ -1,6 +1,5 @@ -const chai = require("chai"); -const expect = chai.expect; -const Lookup = require("../../src/us_enrichment/Lookup"); +import { expect } from "chai"; +import Lookup from "../../src/us_enrichment/Lookup.js"; describe("A US Enrichment Lookup", function () { it("can be newed up with all basic fields.", function () { @@ -26,4 +25,4 @@ describe("A US Enrichment Lookup", function () { expect(lookup.dataSubset).to.equal(expectedDataSubset); expect(lookup.features).to.equal(expectedFeatures); }); -}); \ No newline at end of file +}); diff --git a/tests/us_enrichment/test_Response.js b/tests/us_enrichment/test_Response.js deleted file mode 100644 index 0c4b549..0000000 --- a/tests/us_enrichment/test_Response.js +++ /dev/null @@ -1,739 +0,0 @@ -const chai = require("chai"); -const expect = chai.expect; -const {Response} = require("../../src/us_enrichment/Response.js"); - -describe("A US Enrichment Response", function () { - it("is initialized correctly with API response data.", function () { - const mockResponse = { - smarty_key: "a", - data_set_name: "b", - data_subset_name: "c", - attributes: { - "1st_floor_sqft": "01", - "2nd_floor_sqft": "02", - acres: "0", - address_info_privacy: "1", - air_conditioner: "2", - arbor_pergola: "3", - assessed_improvement_percent: "4", - assessed_improvement_value: "5", - assessed_land_value: "6", - assessed_value: "7", - assessor_last_update: "8", - assessor_taxroll_update: "9", - attic_area: "10", - attic_flag: "11", - balcony: "12", - balcony_area: "13", - basement_sqft: "14", - basement_sqft_finished: "15", - basement_sqft_unfinished: "16", - bath_house: "17", - bath_house_sqft: "18", - bathrooms_partial: "19", - bathrooms_total: "20", - bedrooms: "21", - block_1: "22", - block_2: "23", - boat_access: "24", - boat_house: "25", - boat_house_sqft: "26", - boat_lift: "27", - bonus_room: "28", - breakfast_nook: "29", - breezeway: "30", - building_definition: "31", - building_sqft: "32", - cabin: "33", - cabin_sqft: "34", - canopy: "35", - canopy_sqft: "36", - carport: "37", - carport_sqft: "38", - cbsa_code: "39", - cbsa_name: "40", - cellar: "41", - census_block: "42", - census_block_group: "43", - census_fips_place_code: "44", - census_tract: "45", - central_vacuum: "46", - code_title_company: "47", - combined_statistical_area: "48", - community_rec: "49", - company_flag: "50", - congressional_district: "51", - construction_type: "52", - contact_city: "53", - contact_crrt: "54", - contact_full_address: "55", - contact_house_number: "56", - contact_main_info_format: "57", - contact_mail_info_privacy: "58", - contact_mailing_county: "59", - contact_mailing_fips: "60", - contact_post_direction: "61", - contact_pre_direction: "62", - contact_state: "63", - contact_street_name: "64", - contact_suffix: "65", - contact_unit_designator: "66", - contact_value: "67", - contact_zip: "68", - contact_zip4: "69", - courtyard: "70", - courtyard_area: "71", - deck: "72", - deck_area: "73", - deed_document_page: "74", - deed_document_book: "75", - deed_document_number: "76", - deed_owner_first_name: "77", - deed_owner_first_name2: "78", - deed_owner_first_name3: "79", - deed_owner_first_name4: "80", - deed_owner_full_name: "81", - deed_owner_full_name2: "82", - deed_owner_full_name3: "83", - deed_owner_full_name4: "84", - deed_owner_last_name: "85", - deed_owner_last_name2: "86", - deed_owner_last_name3: "87", - deed_owner_last_name4: "88", - deed_owner_middle_name: "89", - deed_owner_middle_name2: "90", - deed_owner_middle_name3: "91", - deed_owner_middle_name4: "92", - deed_owner_suffix: "93", - deed_owner_suffix2: "94", - deed_owner_suffix3: "95", - deed_owner_suffix4: "96", - deed_sale_date: "97", - deed_sale_price: "98", - deed_transaction_id: "99", - depth_linear_footage: "100", - disabled_tax_exemption: "101", - driveway_sqft: "102", - driveway_type: "103", - effective_year_built: "104", - elevation_feet: "105", - elevator: "106", - equestrian_arena: "107", - escalator: "108", - exercise_room: "109", - exterior_walls: "110", - family_room: "111", - fence: "112", - fence_area: "113", - fips_code: "114", - fire_resistance_code: "115", - fire_sprinkler_flag: "116", - fireplace: "117", - fireplace_number: "118", - first_name: "119", - first_name2: "120", - first_name3: "121", - first_name4: "122", - flooring: "123", - foundation: "124", - game_room: "125", - garage: "126", - garage_sqft: "127", - gazebo: "128", - gazebo_sqft: "129", - golf_course: "130", - grainery: "131", - grainery_sqft: "132", - great_room: "133", - greenhouse: "134", - greenhouse_sqft: "135", - gross_sqft: "136", - guesthouse: "137", - guesthouse_sqft: "138", - handicap_accessibility: "139", - heat: "140", - heat_fuel_type: "141", - hobby_room: "142", - homeowner_tax_exemption: "143", - instrument_date: "144", - intercom_system: "145", - interest_rate_type_2: "146", - interior_structure: "147", - kennel: "148", - kennel_sqft: "149", - land_use_code: "150", - land_use_group: "151", - land_use_standard: "152", - last_name: "153", - last_name_2: "154", - last_name_3: "155", - last_name_4: "156", - latitude: "157", - laundry: "158", - lean_to: "159", - lean_to_sqft: "160", - legal_description: "161", - legal_unit: "162", - lender_address: "163", - lender_address_2: "164", - lender_city: "165", - lender_city_2: "166", - lender_code: "167", - lender_code_2: "168", - lender_first_name: "169", - lender_first_name_2: "170", - lender_last_name: "171", - lender_last_name_2: "172", - lender_name: "173", - lender_name_2: "174", - lender_seller_carry_back: "175", - lender_seller_carry_back_2: "176", - lender_state: "177", - lender_state_2: "178", - lender_zip: "179", - lender_zip_2: "180", - lender_zip_extended: "181", - lender_zip_extended_2: "182", - loading_platform: "183", - loading_platform_sqft: "184", - longitude: "185", - lot_1: "186", - lot_2: "187", - lot_3: "188", - lot_sqft: "189", - market_improvement_percent: "190", - market_improvement_value: "191", - market_land_value: "192", - market_value_year: "193", - match_type: "194", - media_room: "195", - metro_division: "196", - middle_name: "197", - middle_name_2: "198", - middle_name_3: "199", - middle_name_4: "200", - milkhouse: "201", - milkhouse_sqft: "202", - minor_civil_division_code: "203", - minor_civil_division_name: "204", - mobile_home_hookup: "205", - mortgage_amount: "206", - mortgage_amount_2: "207", - mortgage_due_date: "208", - mortgage_due_date_2: "209", - mortgage_interest_rate: "210", - mortgage_interest_rate_type: "211", - mortgage_lender_code: "212", - mortgage_rate_2: "213", - mortgage_recording_date: "214", - mortgage_recording_date_2: "215", - mortgage_term: "216", - mortgage_term_2: "217", - mortgage_term_type: "218", - mortgage_term_type_2: "219", - mortgage_type: "220", - mortgage_type_2: "221", - msa_code: "222", - msa_name: "223", - mud_room: "224", - multi_parcel_flag: "225", - name_title_company: "226", - neighborhood_code: "227", - number_of_buildings: "228", - office: "229", - office_sqft: "230", - other_tax_exemption: "231", - outdoor_kitchen_fireplace: "232", - overhead_door: "233", - owner_full_name: "234", - owner_full_name_2: "235", - owner_full_name_3: "236", - owner_full_name_4: "237", - owner_occupancy_status: "238", - ownership_transfer_date: "239", - ownership_transfer_doc_number: "240", - ownership_transfer_transaction_id: "241", - ownership_type: "242", - ownership_type_2: "243", - ownership_vesting_relation_code: "244", - parcel_account_number: "245", - parcel_map_book: "246", - parcel_map_page: "247", - parcel_number_alternate: "248", - parcel_number_formatted: "249", - parcel_number_previous: "250", - parcel_number_year_added: "251", - parcel_number_year_change: "252", - parcel_raw_number: "253", - parcel_shell_record: "254", - parking_spaces: "255", - patio_area: "256", - phase_name: "257", - plumbing_fixtures_count: "257", - pole_struct: "258", - pole_struct_sqft: "259", - pond: "260", - pool: "261", - pool_area: "262", - poolhouse: "263", - poolhouse_sqft: "264", - porch: "265", - porch_area: "266", - poultry_house: "267", - poultry_house_sqft: "268", - previous_assessed_value: "269", - prior_sale_amount: "270", - prior_sale_date: "271", - property_address_carrier_route_code: "272", - property_address_city: "273", - property_address_full: "274", - property_address_house_number: "275", - property_address_post_direction: "276", - property_address_pre_direction: "277", - property_address_state: "278", - property_address_street_name: "279", - property_address_street_suffix: "280", - property_address_unit_designator: "281", - property_address_unit_value: "282", - property_address_zip_4: "283", - property_address_zipcode: "284", - publication_date: "285", - quarter: "286", - quarter_quarter: "287", - quonset: "288", - quonset_sqft: "289", - range: "290", - recording_date: "291", - roof_cover: "292", - roof_frame: "293", - rooms: "294", - rv_parking: "295", - safe_room: "296", - sale_amount: "297", - sale_date: "298", - sauna: "299", - section: "300", - security_alarm: "301", - senior_tax_exemption: "302", - sewer_type: "303", - shed: "304", - shed_sqft: "305", - silo: "306", - silo_sqft: "307", - sitting_room: "308", - situs_county: "309", - situs_state: "310", - sound_system: "311", - sports_court: "312", - sprinklers: "313", - stable: "314", - stable_sqft: "315", - storage_building: "316", - storage_buildling_sqft: "317", - stories_number: "318", - storm_shelter: "319", - storm_shutter: "320", - structure_style: "321", - study: "322", - subdivision: "323", - suffix: "324", - suffix_2: "325", - suffix_3: "326", - suffix_4: "327", - sunroom: "328", - tax_assess_year: "329", - tax_billed_amount: "330", - tax_delinquent_year: "331", - tax_fiscal_year: "332", - tax_jurisdiction: "333", - tax_rate_area: "334", - tennis_court: "335", - topography_code: "336", - total_market_value: "337", - township: "338", - tract_number: "339", - transfer_amount: "340", - trust_description: "341", - unit_count: "342", - upper_floors_sqft: "343", - utility: "344", - utility_building: "345", - utility_building_sqft: "346", - utility_sqft: "347", - veteran_tax_exemption: "348", - view_description: "349", - water_feature: "350", - water_service_type: "351", - wet_bar: "352", - widow_tax_exemption: "353", - width_linear_footage: "354", - wine_cellar: "355", - year_built: "356", - zoning: "357", - }, - }; - let response = new Response(mockResponse); - - expect(response.attributes.firstFloorSqft).to.equal("01"); - expect(response.attributes.secondFlootSqft).to.equal("02"); - expect(response.attributes.acres).to.equal("0"); - expect(response.attributes.addressInfoPrivacy).to.equal("1"); - expect(response.attributes.airConditioner).to.equal("2"); - expect(response.attributes.arborPergola).to.equal("3"); - expect(response.attributes.assessedImprovementPercent).to.equal("4"); - expect(response.attributes.assessedImprovementValue).to.equal("5"); - expect(response.attributes.assessedLandValue).to.equal("6"); - expect(response.attributes.assessedValue).to.equal("7"); - expect(response.attributes.assessorLastUpdate).to.equal("8"); - expect(response.attributes.assessorTaxrollUpdate).to.equal("9"); - expect(response.attributes.atticArea).to.equal("10"); - expect(response.attributes.atticFlag).to.equal("11"); - expect(response.attributes.balcony).to.equal("12"); - expect(response.attributes.balconyArea).to.equal("13"); - expect(response.attributes.basementSqft).to.equal("14"); - expect(response.attributes.basementSqftFinished).to.equal("15"); - expect(response.attributes.basementsqftUnfinished).to.equal("16"); - expect(response.attributes.bathHouse).to.equal("17"); - expect(response.attributes.bathHouseSqft).to.equal("18"); - expect(response.attributes.bathroomsPartial).to.equal("19"); - expect(response.attributes.bathroomsTotal).to.equal("20"); - expect(response.attributes.bedrooms).to.equal("21"); - expect(response.attributes.block1).to.equal("22"); - expect(response.attributes.block2).to.equal("23"); - expect(response.attributes.boatAccess).to.equal("24"); - expect(response.attributes.boatHouse).to.equal("25"); - expect(response.attributes.boatHouseSqft).to.equal("26"); - expect(response.attributes.boatLift).to.equal("27"); - expect(response.attributes.bonusRoom).to.equal("28"); - expect(response.attributes.breakfastNook).to.equal("29"); - expect(response.attributes.breezeway).to.equal("30"); - expect(response.attributes.buildingDefinitionCode).to.equal("31"); - expect(response.attributes.buildingSqft).to.equal("32"); - expect(response.attributes.cabin).to.equal("33"); - expect(response.attributes.cabinSqft).to.equal("34"); - expect(response.attributes.canopy).to.equal("35"); - expect(response.attributes.canopySqft).to.equal("36"); - expect(response.attributes.carport).to.equal("37"); - expect(response.attributes.carportSqft).to.equal("38"); - expect(response.attributes.cbsaCode).to.equal("39"); - expect(response.attributes.cbsaName).to.equal("40"); - expect(response.attributes.cellar).to.equal("41"); - expect(response.attributes.censusBlock).to.equal("42"); - expect(response.attributes.censusBlockGroup).to.equal("43"); - expect(response.attributes.censusFipsPlaceCode).to.equal("44"); - expect(response.attributes.censusTract).to.equal("45"); - expect(response.attributes.centralVacuum).to.equal("46"); - expect(response.attributes.codeTitleCompany).to.equal("47"); - expect(response.attributes.combinedStatisticalArea).to.equal("48"); - expect(response.attributes.communityRec).to.equal("49"); - expect(response.attributes.companyFlag).to.equal("50"); - expect(response.attributes.congressionalDistrict).to.equal("51"); - expect(response.attributes.constructionType).to.equal("52"); - expect(response.attributes.contactCity).to.equal("53"); - expect(response.attributes.contactCrrt).to.equal("54"); - expect(response.attributes.contactFullAddress).to.equal("55"); - expect(response.attributes.contactHouseNumber).to.equal("56"); - expect(response.attributes.contactMailInfoFormat).to.equal("57"); - expect(response.attributes.contactMailInfoPrivacy).to.equal("58"); - expect(response.attributes.contactMailingCounty).to.equal("59"); - expect(response.attributes.contactMailingFips).to.equal("60"); - expect(response.attributes.contactPostDirection).to.equal("61"); - expect(response.attributes.contactPreDirection).to.equal("62"); - expect(response.attributes.contactState).to.equal("63"); - expect(response.attributes.contactStreetName).to.equal("64"); - expect(response.attributes.contactSuffix).to.equal("65"); - expect(response.attributes.contactUnitDesignator).to.equal("66"); - expect(response.attributes.contactValue).to.equal("67"); - expect(response.attributes.contactZip).to.equal("68"); - expect(response.attributes.contactZip4).to.equal("69"); - expect(response.attributes.courtyard).to.equal("70"); - expect(response.attributes.courtyardArea).to.equal("71"); - expect(response.attributes.deck).to.equal("72"); - expect(response.attributes.deckArea).to.equal("73"); - expect(response.attributes.deedDocumentPage).to.equal("74"); - expect(response.attributes.deedDocumentBook).to.equal("75"); - expect(response.attributes.deedDocumentNumber).to.equal("76"); - expect(response.attributes.deedOwnerFirstName).to.equal("77"); - expect(response.attributes.deedOwnerFirstName2).to.equal("78"); - expect(response.attributes.deedOwnerFirstName3).to.equal("79"); - expect(response.attributes.deedOwnerFirstName4).to.equal("80"); - expect(response.attributes.deedOwnerFullName).to.equal("81"); - expect(response.attributes.deedOwnerFullName2).to.equal("82"); - expect(response.attributes.deedOwnerFullName3).to.equal("83"); - expect(response.attributes.deedOwnerFullName4).to.equal("84"); - expect(response.attributes.deedOwnerLastName).to.equal("85"); - expect(response.attributes.deedOwnerLastName2).to.equal("86"); - expect(response.attributes.deedOwnerLastName3).to.equal("87"); - expect(response.attributes.deedOwnerLastName4).to.equal("88"); - expect(response.attributes.deedOwnerMiddleName).to.equal("89"); - expect(response.attributes.deedOwnerMiddleName2).to.equal("90"); - expect(response.attributes.deedOwnerMiddleName3).to.equal("91"); - expect(response.attributes.deedOwnerMiddleName4).to.equal("92"); - expect(response.attributes.deedOwnerSuffix).to.equal("93"); - expect(response.attributes.deedOwnerSuffix2).to.equal("94"); - expect(response.attributes.deedOwnerSuffix3).to.equal("95"); - expect(response.attributes.deedOwnerSuffix4).to.equal("96"); - expect(response.attributes.deedSaleDate).to.equal("97"); - expect(response.attributes.deedSalePrice).to.equal("98"); - expect(response.attributes.deedTransactionId).to.equal("99"); - expect(response.attributes.depthLinearFootage).to.equal("100"); - expect(response.attributes.disabledTaxExemption).to.equal("101"); - expect(response.attributes.drivewaySqft).to.equal("102"); - expect(response.attributes.drivewayType).to.equal("103"); - expect(response.attributes.effectiveYearBuilt).to.equal("104"); - expect(response.attributes.elevationFeet).to.equal("105"); - expect(response.attributes.elevator).to.equal("106"); - expect(response.attributes.equestrianArena).to.equal("107"); - expect(response.attributes.escalator).to.equal("108"); - expect(response.attributes.exerciseRoom).to.equal("109"); - expect(response.attributes.exteriorWalls).to.equal("110"); - expect(response.attributes.familyRoom).to.equal("111"); - expect(response.attributes.fence).to.equal("112"); - expect(response.attributes.fenceArea).to.equal("113"); - expect(response.attributes.fipsCode).to.equal("114"); - expect(response.attributes.fireResistanceCode).to.equal("115"); - expect(response.attributes.fireSprinklersFlag).to.equal("116"); - expect(response.attributes.fireplace).to.equal("117"); - expect(response.attributes.fireplaceNumber).to.equal("118"); - expect(response.attributes.firstName).to.equal("119"); - expect(response.attributes.firstName2).to.equal("120"); - expect(response.attributes.firstName3).to.equal("121"); - expect(response.attributes.firstName4).to.equal("122"); - expect(response.attributes.flooring).to.equal("123"); - expect(response.attributes.foundation).to.equal("124"); - expect(response.attributes.gameRoom).to.equal("125"); - expect(response.attributes.garage).to.equal("126"); - expect(response.attributes.garageSqft).to.equal("127"); - expect(response.attributes.gazebo).to.equal("128"); - expect(response.attributes.gazeboSqft).to.equal("129"); - expect(response.attributes.golfCourse).to.equal("130"); - expect(response.attributes.grainery).to.equal("131"); - expect(response.attributes.grainerySqft).to.equal("132"); - expect(response.attributes.greatRoom).to.equal("133"); - expect(response.attributes.greenhouse).to.equal("134"); - expect(response.attributes.greenhouseSqft).to.equal("135"); - expect(response.attributes.grossSqft).to.equal("136"); - expect(response.attributes.guesthouse).to.equal("137"); - expect(response.attributes.guesthouseSqft).to.equal("138"); - expect(response.attributes.handicapAccessibility).to.equal("139"); - expect(response.attributes.heat).to.equal("140"); - expect(response.attributes.heatFuelType).to.equal("141"); - expect(response.attributes.hobbyRoom).to.equal("142"); - expect(response.attributes.homeownerTaxExemption).to.equal("143"); - expect(response.attributes.instrumentDate).to.equal("144"); - expect(response.attributes.intercomSystem).to.equal("145"); - expect(response.attributes.interestRateType2).to.equal("146"); - expect(response.attributes.interiorStructure).to.equal("147"); - expect(response.attributes.kennel).to.equal("148"); - expect(response.attributes.kennelSqft).to.equal("149"); - expect(response.attributes.landUseCode).to.equal("150"); - expect(response.attributes.landUseGroup).to.equal("151"); - expect(response.attributes.landUseStandard).to.equal("152"); - expect(response.attributes.lastName).to.equal("153"); - expect(response.attributes.lastName2).to.equal("154"); - expect(response.attributes.lastName3).to.equal("155"); - expect(response.attributes.lastName4).to.equal("156"); - expect(response.attributes.latitude).to.equal("157"); - expect(response.attributes.laundry).to.equal("158"); - expect(response.attributes.leanTo).to.equal("159"); - expect(response.attributes.leanToSqft).to.equal("160"); - expect(response.attributes.legalDescription).to.equal("161"); - expect(response.attributes.legalUnit).to.equal("162"); - expect(response.attributes.lenderAddress).to.equal("163"); - expect(response.attributes.lenderAddress2).to.equal("164"); - expect(response.attributes.lenderCity).to.equal("165"); - expect(response.attributes.lenderCity2).to.equal("166"); - expect(response.attributes.lenderCode).to.equal("167"); - expect(response.attributes.lenderCode2).to.equal("168"); - expect(response.attributes.lenderFirstName).to.equal("169"); - expect(response.attributes.lenderFirstName2).to.equal("170"); - expect(response.attributes.lenderLastName).to.equal("171"); - expect(response.attributes.lenderLastName2).to.equal("172"); - expect(response.attributes.lenderName).to.equal("173"); - expect(response.attributes.lenderName2).to.equal("174"); - expect(response.attributes.lenderSellerCarryBack).to.equal("175"); - expect(response.attributes.lenderSellerCarryBack2).to.equal("176"); - expect(response.attributes.lenderState).to.equal("177"); - expect(response.attributes.lenderState2).to.equal("178"); - expect(response.attributes.lenderZip).to.equal("179"); - expect(response.attributes.lenderZip2).to.equal("180"); - expect(response.attributes.lenderZipExtended).to.equal("181"); - expect(response.attributes.lenderZipExtended2).to.equal("182"); - expect(response.attributes.loadingPlatform).to.equal("183"); - expect(response.attributes.loadingPlatformSqft).to.equal("184"); - expect(response.attributes.longitude).to.equal("185"); - expect(response.attributes.lot1).to.equal("186"); - expect(response.attributes.lot2).to.equal("187"); - expect(response.attributes.lot3).to.equal("188"); - expect(response.attributes.lotSqft).to.equal("189"); - expect(response.attributes.marketImprovementPercent).to.equal("190"); - expect(response.attributes.marketImprovementValue).to.equal("191"); - expect(response.attributes.marketLandValue).to.equal("192"); - expect(response.attributes.marketValueYear).to.equal("193"); - expect(response.attributes.matchType).to.equal("194"); - expect(response.attributes.mediaRoom).to.equal("195"); - expect(response.attributes.metroDivision).to.equal("196"); - expect(response.attributes.middleName).to.equal("197"); - expect(response.attributes.middleName2).to.equal("198"); - expect(response.attributes.middleName3).to.equal("199"); - expect(response.attributes.middleName4).to.equal("200"); - expect(response.attributes.milkhouse).to.equal("201"); - expect(response.attributes.milkhouseSqft).to.equal("202"); - expect(response.attributes.minorCivilDivisionCode).to.equal("203"); - expect(response.attributes.minorCivilDivisionName).to.equal("204"); - expect(response.attributes.mobileHomeHookup).to.equal("205"); - expect(response.attributes.mortgageAmount).to.equal("206"); - expect(response.attributes.mortgageAmount2).to.equal("207"); - expect(response.attributes.mortgageDueDate).to.equal("208"); - expect(response.attributes.mortgageDueDate2).to.equal("209"); - expect(response.attributes.mortgageInterestRate).to.equal("210"); - expect(response.attributes.mortgageInterestRateType).to.equal("211"); - expect(response.attributes.mortgageLenderCode).to.equal("212"); - expect(response.attributes.mortgageRate2).to.equal("213"); - expect(response.attributes.mortgageRecordingDate).to.equal("214"); - expect(response.attributes.mortgageRecordingDate2).to.equal("215"); - expect(response.attributes.mortgageTerm).to.equal("216"); - expect(response.attributes.mortgageTerm2).to.equal("217"); - expect(response.attributes.mortgageTermType).to.equal("218"); - expect(response.attributes.mortgageTermType2).to.equal("219"); - expect(response.attributes.mortgageType).to.equal("220"); - expect(response.attributes.mortgageType2).to.equal("221"); - expect(response.attributes.msaCode).to.equal("222"); - expect(response.attributes.msaName).to.equal("223"); - expect(response.attributes.mudRoom).to.equal("224"); - expect(response.attributes.multiParcelFlag).to.equal("225"); - expect(response.attributes.nameTitleCompany).to.equal("226"); - expect(response.attributes.neighborhoodCode).to.equal("227"); - expect(response.attributes.numberOfBuildings).to.equal("228"); - expect(response.attributes.office).to.equal("229"); - expect(response.attributes.officeSqft).to.equal("230"); - expect(response.attributes.otherTaxExemption).to.equal("231"); - expect(response.attributes.outdoorKitchenFireplace).to.equal("232"); - expect(response.attributes.overheadDoor).to.equal("233"); - expect(response.attributes.ownerFullName).to.equal("234"); - expect(response.attributes.ownerFullName2).to.equal("235"); - expect(response.attributes.ownerFullName3).to.equal("236"); - expect(response.attributes.ownerFullName4).to.equal("237"); - expect(response.attributes.ownerOccupancyStatus).to.equal("238"); - expect(response.attributes.ownershipTransferDate).to.equal("239"); - expect(response.attributes.ownershipTransferDocNumber).to.equal("240"); - expect(response.attributes.ownershipTransferTransactionId).to.equal("241"); - expect(response.attributes.ownershipType).to.equal("242"); - expect(response.attributes.ownershipType2).to.equal("243"); - expect(response.attributes.ownershipVestingRelationCode).to.equal("244"); - expect(response.attributes.parcelAccountNumber).to.equal("245"); - expect(response.attributes.parcelMapBook).to.equal("246"); - expect(response.attributes.parcelMapPage).to.equal("247"); - expect(response.attributes.parcelNumberAlternate).to.equal("248"); - expect(response.attributes.parcelNumberFormatted).to.equal("249"); - expect(response.attributes.parcelNumberPrevious).to.equal("250"); - expect(response.attributes.parcelNumberYearAdded).to.equal("251"); - expect(response.attributes.parcelNumberYearChange).to.equal("252"); - expect(response.attributes.parcelRawNumber).to.equal("253"); - expect(response.attributes.parcelShellRecord).to.equal("254"); - expect(response.attributes.parkingSpaces).to.equal("255"); - expect(response.attributes.patioArea).to.equal("256"); - expect(response.attributes.phaseName).to.equal("257"); - expect(response.attributes.plumbingFixturesCount).to.equal("257"); - expect(response.attributes.poleStruct).to.equal("258"); - expect(response.attributes.poleStructSqft).to.equal("259"); - expect(response.attributes.pond).to.equal("260"); - expect(response.attributes.pool).to.equal("261"); - expect(response.attributes.poolArea).to.equal("262"); - expect(response.attributes.poolhouse).to.equal("263"); - expect(response.attributes.poolhouseSqft).to.equal("264"); - expect(response.attributes.porch).to.equal("265"); - expect(response.attributes.porchArea).to.equal("266"); - expect(response.attributes.poultryHouse).to.equal("267"); - expect(response.attributes.poultryHouseSqft).to.equal("268"); - expect(response.attributes.previousAssessedValue).to.equal("269"); - expect(response.attributes.priorSaleAmount).to.equal("270"); - expect(response.attributes.priorSaleDate).to.equal("271"); - expect(response.attributes.propertyAddressCarrierRouteCode).to.equal("272"); - expect(response.attributes.propertyAddressCity).to.equal("273"); - expect(response.attributes.propertyAddressFull).to.equal("274"); - expect(response.attributes.propertyAddressHouseNumber).to.equal("275"); - expect(response.attributes.propertyAddressPostDirection).to.equal("276"); - expect(response.attributes.propertyAddressPreDirection).to.equal("277"); - expect(response.attributes.propertyAddressState).to.equal("278"); - expect(response.attributes.propertyAddressStreetName).to.equal("279"); - expect(response.attributes.propertyAddressStreetSuffix).to.equal("280"); - expect(response.attributes.propertyAddressUnitDesignator).to.equal("281"); - expect(response.attributes.propertyAddressUnitValue).to.equal("282"); - expect(response.attributes.propertyAddressZip4).to.equal("283"); - expect(response.attributes.propertyAddressZipcode).to.equal("284"); - expect(response.attributes.publicationDate).to.equal("285"); - expect(response.attributes.quarter).to.equal("286"); - expect(response.attributes.quarterQuarter).to.equal("287"); - expect(response.attributes.quonset).to.equal("288"); - expect(response.attributes.quonsetSqft).to.equal("289"); - expect(response.attributes.range).to.equal("290"); - expect(response.attributes.recordingDate).to.equal("291"); - expect(response.attributes.roofCover).to.equal("292"); - expect(response.attributes.roofFrame).to.equal("293"); - expect(response.attributes.rooms).to.equal("294"); - expect(response.attributes.rvParking).to.equal("295"); - expect(response.attributes.safeRoom).to.equal("296"); - expect(response.attributes.saleAmount).to.equal("297"); - expect(response.attributes.saleDate).to.equal("298"); - expect(response.attributes.sauna).to.equal("299"); - expect(response.attributes.section).to.equal("300"); - expect(response.attributes.securityAlarm).to.equal("301"); - expect(response.attributes.seniorTaxExemption).to.equal("302"); - expect(response.attributes.sewerType).to.equal("303"); - expect(response.attributes.shed).to.equal("304"); - expect(response.attributes.shedSqft).to.equal("305"); - expect(response.attributes.silo).to.equal("306"); - expect(response.attributes.siloSqft).to.equal("307"); - expect(response.attributes.sittingRoom).to.equal("308"); - expect(response.attributes.situsCounty).to.equal("309"); - expect(response.attributes.situsState).to.equal("310"); - expect(response.attributes.soundSystem).to.equal("311"); - expect(response.attributes.sportsCourt).to.equal("312"); - expect(response.attributes.sprinklers).to.equal("313"); - expect(response.attributes.stable).to.equal("314"); - expect(response.attributes.stableSqft).to.equal("315"); - expect(response.attributes.storageBuilding).to.equal("316"); - expect(response.attributes.storageBuildingSqft).to.equal("317"); - expect(response.attributes.storiesNumber).to.equal("318"); - expect(response.attributes.stormShelter).to.equal("319"); - expect(response.attributes.stormShutter).to.equal("320"); - expect(response.attributes.structureStyle).to.equal("321"); - expect(response.attributes.study).to.equal("322"); - expect(response.attributes.subdivision).to.equal("323"); - expect(response.attributes.suffix).to.equal("324"); - expect(response.attributes.suffix2).to.equal("325"); - expect(response.attributes.suffix3).to.equal("326"); - expect(response.attributes.suffix4).to.equal("327"); - expect(response.attributes.sunroom).to.equal("328"); - expect(response.attributes.taxAssessYear).to.equal("329"); - expect(response.attributes.taxBilledAmount).to.equal("330"); - expect(response.attributes.taxDelinquentYear).to.equal("331"); - expect(response.attributes.taxFiscalYear).to.equal("332"); - expect(response.attributes.taxJurisdiction).to.equal("333"); - expect(response.attributes.taxRateArea).to.equal("334"); - expect(response.attributes.tennisCourt).to.equal("335"); - expect(response.attributes.topographyCode).to.equal("336"); - expect(response.attributes.totalMarketValue).to.equal("337"); - expect(response.attributes.township).to.equal("338"); - expect(response.attributes.tractNumber).to.equal("339"); - expect(response.attributes.transferAmount).to.equal("340"); - expect(response.attributes.trustDescription).to.equal("341"); - expect(response.attributes.unitCount).to.equal("342"); - expect(response.attributes.upperFloorsSqft).to.equal("343"); - expect(response.attributes.utility).to.equal("344"); - expect(response.attributes.utilityBuilding).to.equal("345"); - expect(response.attributes.utilityBuildingSqft).to.equal("346"); - expect(response.attributes.utilitySqft).to.equal("347"); - expect(response.attributes.veteranTaxExemption).to.equal("348"); - expect(response.attributes.viewDescription).to.equal("349"); - expect(response.attributes.waterFeature).to.equal("350"); - expect(response.attributes.waterServiceType).to.equal("351"); - expect(response.attributes.wetBar).to.equal("352"); - expect(response.attributes.widowTaxExemption).to.equal("353"); - expect(response.attributes.widthLinearFootage).to.equal("354"); - expect(response.attributes.wineCellar).to.equal("355"); - expect(response.attributes.yearBuilt).to.equal("356"); - expect(response.attributes.zoning).to.equal("357"); - }); -}); \ No newline at end of file diff --git a/tests/us_enrichment/test_Response.ts b/tests/us_enrichment/test_Response.ts new file mode 100644 index 0000000..970c45f --- /dev/null +++ b/tests/us_enrichment/test_Response.ts @@ -0,0 +1,738 @@ +import { expect } from "chai"; +import { Response } from "../../src/us_enrichment/Response.js"; + +describe("A US Enrichment Response", function () { + it("is initialized correctly with API response data.", function () { + const mockResponse = { + smarty_key: "a", + data_set_name: "b", + data_subset_name: "c", + attributes: { + "1st_floor_sqft": "01", + "2nd_floor_sqft": "02", + acres: "0", + address_info_privacy: "1", + air_conditioner: "2", + arbor_pergola: "3", + assessed_improvement_percent: "4", + assessed_improvement_value: "5", + assessed_land_value: "6", + assessed_value: "7", + assessor_last_update: "8", + assessor_taxroll_update: "9", + attic_area: "10", + attic_flag: "11", + balcony: "12", + balcony_area: "13", + basement_sqft: "14", + basement_sqft_finished: "15", + basement_sqft_unfinished: "16", + bath_house: "17", + bath_house_sqft: "18", + bathrooms_partial: "19", + bathrooms_total: "20", + bedrooms: "21", + block_1: "22", + block_2: "23", + boat_access: "24", + boat_house: "25", + boat_house_sqft: "26", + boat_lift: "27", + bonus_room: "28", + breakfast_nook: "29", + breezeway: "30", + building_definition: "31", + building_sqft: "32", + cabin: "33", + cabin_sqft: "34", + canopy: "35", + canopy_sqft: "36", + carport: "37", + carport_sqft: "38", + cbsa_code: "39", + cbsa_name: "40", + cellar: "41", + census_block: "42", + census_block_group: "43", + census_fips_place_code: "44", + census_tract: "45", + central_vacuum: "46", + code_title_company: "47", + combined_statistical_area: "48", + community_rec: "49", + company_flag: "50", + congressional_district: "51", + construction_type: "52", + contact_city: "53", + contact_crrt: "54", + contact_full_address: "55", + contact_house_number: "56", + contact_main_info_format: "57", + contact_mail_info_privacy: "58", + contact_mailing_county: "59", + contact_mailing_fips: "60", + contact_post_direction: "61", + contact_pre_direction: "62", + contact_state: "63", + contact_street_name: "64", + contact_suffix: "65", + contact_unit_designator: "66", + contact_value: "67", + contact_zip: "68", + contact_zip4: "69", + courtyard: "70", + courtyard_area: "71", + deck: "72", + deck_area: "73", + deed_document_page: "74", + deed_document_book: "75", + deed_document_number: "76", + deed_owner_first_name: "77", + deed_owner_first_name2: "78", + deed_owner_first_name3: "79", + deed_owner_first_name4: "80", + deed_owner_full_name: "81", + deed_owner_full_name2: "82", + deed_owner_full_name3: "83", + deed_owner_full_name4: "84", + deed_owner_last_name: "85", + deed_owner_last_name2: "86", + deed_owner_last_name3: "87", + deed_owner_last_name4: "88", + deed_owner_middle_name: "89", + deed_owner_middle_name2: "90", + deed_owner_middle_name3: "91", + deed_owner_middle_name4: "92", + deed_owner_suffix: "93", + deed_owner_suffix2: "94", + deed_owner_suffix3: "95", + deed_owner_suffix4: "96", + deed_sale_date: "97", + deed_sale_price: "98", + deed_transaction_id: "99", + depth_linear_footage: "100", + disabled_tax_exemption: "101", + driveway_sqft: "102", + driveway_type: "103", + effective_year_built: "104", + elevation_feet: "105", + elevator: "106", + equestrian_arena: "107", + escalator: "108", + exercise_room: "109", + exterior_walls: "110", + family_room: "111", + fence: "112", + fence_area: "113", + fips_code: "114", + fire_resistance_code: "115", + fire_sprinkler_flag: "116", + fireplace: "117", + fireplace_number: "118", + first_name: "119", + first_name2: "120", + first_name3: "121", + first_name4: "122", + flooring: "123", + foundation: "124", + game_room: "125", + garage: "126", + garage_sqft: "127", + gazebo: "128", + gazebo_sqft: "129", + golf_course: "130", + grainery: "131", + grainery_sqft: "132", + great_room: "133", + greenhouse: "134", + greenhouse_sqft: "135", + gross_sqft: "136", + guesthouse: "137", + guesthouse_sqft: "138", + handicap_accessibility: "139", + heat: "140", + heat_fuel_type: "141", + hobby_room: "142", + homeowner_tax_exemption: "143", + instrument_date: "144", + intercom_system: "145", + interest_rate_type_2: "146", + interior_structure: "147", + kennel: "148", + kennel_sqft: "149", + land_use_code: "150", + land_use_group: "151", + land_use_standard: "152", + last_name: "153", + last_name_2: "154", + last_name_3: "155", + last_name_4: "156", + latitude: "157", + laundry: "158", + lean_to: "159", + lean_to_sqft: "160", + legal_description: "161", + legal_unit: "162", + lender_address: "163", + lender_address_2: "164", + lender_city: "165", + lender_city_2: "166", + lender_code: "167", + lender_code_2: "168", + lender_first_name: "169", + lender_first_name_2: "170", + lender_last_name: "171", + lender_last_name_2: "172", + lender_name: "173", + lender_name_2: "174", + lender_seller_carry_back: "175", + lender_seller_carry_back_2: "176", + lender_state: "177", + lender_state_2: "178", + lender_zip: "179", + lender_zip_2: "180", + lender_zip_extended: "181", + lender_zip_extended_2: "182", + loading_platform: "183", + loading_platform_sqft: "184", + longitude: "185", + lot_1: "186", + lot_2: "187", + lot_3: "188", + lot_sqft: "189", + market_improvement_percent: "190", + market_improvement_value: "191", + market_land_value: "192", + market_value_year: "193", + match_type: "194", + media_room: "195", + metro_division: "196", + middle_name: "197", + middle_name_2: "198", + middle_name_3: "199", + middle_name_4: "200", + milkhouse: "201", + milkhouse_sqft: "202", + minor_civil_division_code: "203", + minor_civil_division_name: "204", + mobile_home_hookup: "205", + mortgage_amount: "206", + mortgage_amount_2: "207", + mortgage_due_date: "208", + mortgage_due_date_2: "209", + mortgage_interest_rate: "210", + mortgage_interest_rate_type: "211", + mortgage_lender_code: "212", + mortgage_rate_2: "213", + mortgage_recording_date: "214", + mortgage_recording_date_2: "215", + mortgage_term: "216", + mortgage_term_2: "217", + mortgage_term_type: "218", + mortgage_term_type_2: "219", + mortgage_type: "220", + mortgage_type_2: "221", + msa_code: "222", + msa_name: "223", + mud_room: "224", + multi_parcel_flag: "225", + name_title_company: "226", + neighborhood_code: "227", + number_of_buildings: "228", + office: "229", + office_sqft: "230", + other_tax_exemption: "231", + outdoor_kitchen_fireplace: "232", + overhead_door: "233", + owner_full_name: "234", + owner_full_name_2: "235", + owner_full_name_3: "236", + owner_full_name_4: "237", + owner_occupancy_status: "238", + ownership_transfer_date: "239", + ownership_transfer_doc_number: "240", + ownership_transfer_transaction_id: "241", + ownership_type: "242", + ownership_type_2: "243", + ownership_vesting_relation_code: "244", + parcel_account_number: "245", + parcel_map_book: "246", + parcel_map_page: "247", + parcel_number_alternate: "248", + parcel_number_formatted: "249", + parcel_number_previous: "250", + parcel_number_year_added: "251", + parcel_number_year_change: "252", + parcel_raw_number: "253", + parcel_shell_record: "254", + parking_spaces: "255", + patio_area: "256", + phase_name: "257", + plumbing_fixtures_count: "257", + pole_struct: "258", + pole_struct_sqft: "259", + pond: "260", + pool: "261", + pool_area: "262", + poolhouse: "263", + poolhouse_sqft: "264", + porch: "265", + porch_area: "266", + poultry_house: "267", + poultry_house_sqft: "268", + previous_assessed_value: "269", + prior_sale_amount: "270", + prior_sale_date: "271", + property_address_carrier_route_code: "272", + property_address_city: "273", + property_address_full: "274", + property_address_house_number: "275", + property_address_post_direction: "276", + property_address_pre_direction: "277", + property_address_state: "278", + property_address_street_name: "279", + property_address_street_suffix: "280", + property_address_unit_designator: "281", + property_address_unit_value: "282", + property_address_zip_4: "283", + property_address_zipcode: "284", + publication_date: "285", + quarter: "286", + quarter_quarter: "287", + quonset: "288", + quonset_sqft: "289", + range: "290", + recording_date: "291", + roof_cover: "292", + roof_frame: "293", + rooms: "294", + rv_parking: "295", + safe_room: "296", + sale_amount: "297", + sale_date: "298", + sauna: "299", + section: "300", + security_alarm: "301", + senior_tax_exemption: "302", + sewer_type: "303", + shed: "304", + shed_sqft: "305", + silo: "306", + silo_sqft: "307", + sitting_room: "308", + situs_county: "309", + situs_state: "310", + sound_system: "311", + sports_court: "312", + sprinklers: "313", + stable: "314", + stable_sqft: "315", + storage_building: "316", + storage_buildling_sqft: "317", + stories_number: "318", + storm_shelter: "319", + storm_shutter: "320", + structure_style: "321", + study: "322", + subdivision: "323", + suffix: "324", + suffix_2: "325", + suffix_3: "326", + suffix_4: "327", + sunroom: "328", + tax_assess_year: "329", + tax_billed_amount: "330", + tax_delinquent_year: "331", + tax_fiscal_year: "332", + tax_jurisdiction: "333", + tax_rate_area: "334", + tennis_court: "335", + topography_code: "336", + total_market_value: "337", + township: "338", + tract_number: "339", + transfer_amount: "340", + trust_description: "341", + unit_count: "342", + upper_floors_sqft: "343", + utility: "344", + utility_building: "345", + utility_building_sqft: "346", + utility_sqft: "347", + veteran_tax_exemption: "348", + view_description: "349", + water_feature: "350", + water_service_type: "351", + wet_bar: "352", + widow_tax_exemption: "353", + width_linear_footage: "354", + wine_cellar: "355", + year_built: "356", + zoning: "357", + }, + }; + let response = new Response(mockResponse); + + expect(response.attributes.firstFloorSqft).to.equal("01"); + expect(response.attributes.secondFloorSqft).to.equal("02"); + expect(response.attributes.acres).to.equal("0"); + expect(response.attributes.addressInfoPrivacy).to.equal("1"); + expect(response.attributes.airConditioner).to.equal("2"); + expect(response.attributes.arborPergola).to.equal("3"); + expect(response.attributes.assessedImprovementPercent).to.equal("4"); + expect(response.attributes.assessedImprovementValue).to.equal("5"); + expect(response.attributes.assessedLandValue).to.equal("6"); + expect(response.attributes.assessedValue).to.equal("7"); + expect(response.attributes.assessorLastUpdate).to.equal("8"); + expect(response.attributes.assessorTaxrollUpdate).to.equal("9"); + expect(response.attributes.atticArea).to.equal("10"); + expect(response.attributes.atticFlag).to.equal("11"); + expect(response.attributes.balcony).to.equal("12"); + expect(response.attributes.balconyArea).to.equal("13"); + expect(response.attributes.basementSqft).to.equal("14"); + expect(response.attributes.basementSqftFinished).to.equal("15"); + expect(response.attributes.basementsqftUnfinished).to.equal("16"); + expect(response.attributes.bathHouse).to.equal("17"); + expect(response.attributes.bathHouseSqft).to.equal("18"); + expect(response.attributes.bathroomsPartial).to.equal("19"); + expect(response.attributes.bathroomsTotal).to.equal("20"); + expect(response.attributes.bedrooms).to.equal("21"); + expect(response.attributes.block1).to.equal("22"); + expect(response.attributes.block2).to.equal("23"); + expect(response.attributes.boatAccess).to.equal("24"); + expect(response.attributes.boatHouse).to.equal("25"); + expect(response.attributes.boatHouseSqft).to.equal("26"); + expect(response.attributes.boatLift).to.equal("27"); + expect(response.attributes.bonusRoom).to.equal("28"); + expect(response.attributes.breakfastNook).to.equal("29"); + expect(response.attributes.breezeway).to.equal("30"); + expect(response.attributes.buildingDefinitionCode).to.equal("31"); + expect(response.attributes.buildingSqft).to.equal("32"); + expect(response.attributes.cabin).to.equal("33"); + expect(response.attributes.cabinSqft).to.equal("34"); + expect(response.attributes.canopy).to.equal("35"); + expect(response.attributes.canopySqft).to.equal("36"); + expect(response.attributes.carport).to.equal("37"); + expect(response.attributes.carportSqft).to.equal("38"); + expect(response.attributes.cbsaCode).to.equal("39"); + expect(response.attributes.cbsaName).to.equal("40"); + expect(response.attributes.cellar).to.equal("41"); + expect(response.attributes.censusBlock).to.equal("42"); + expect(response.attributes.censusBlockGroup).to.equal("43"); + expect(response.attributes.censusFipsPlaceCode).to.equal("44"); + expect(response.attributes.censusTract).to.equal("45"); + expect(response.attributes.centralVacuum).to.equal("46"); + expect(response.attributes.codeTitleCompany).to.equal("47"); + expect(response.attributes.combinedStatisticalArea).to.equal("48"); + expect(response.attributes.communityRec).to.equal("49"); + expect(response.attributes.companyFlag).to.equal("50"); + expect(response.attributes.congressionalDistrict).to.equal("51"); + expect(response.attributes.constructionType).to.equal("52"); + expect(response.attributes.contactCity).to.equal("53"); + expect(response.attributes.contactCrrt).to.equal("54"); + expect(response.attributes.contactFullAddress).to.equal("55"); + expect(response.attributes.contactHouseNumber).to.equal("56"); + expect(response.attributes.contactMailInfoFormat).to.equal("57"); + expect(response.attributes.contactMailInfoPrivacy).to.equal("58"); + expect(response.attributes.contactMailingCounty).to.equal("59"); + expect(response.attributes.contactMailingFips).to.equal("60"); + expect(response.attributes.contactPostDirection).to.equal("61"); + expect(response.attributes.contactPreDirection).to.equal("62"); + expect(response.attributes.contactState).to.equal("63"); + expect(response.attributes.contactStreetName).to.equal("64"); + expect(response.attributes.contactSuffix).to.equal("65"); + expect(response.attributes.contactUnitDesignator).to.equal("66"); + expect(response.attributes.contactValue).to.equal("67"); + expect(response.attributes.contactZip).to.equal("68"); + expect(response.attributes.contactZip4).to.equal("69"); + expect(response.attributes.courtyard).to.equal("70"); + expect(response.attributes.courtyardArea).to.equal("71"); + expect(response.attributes.deck).to.equal("72"); + expect(response.attributes.deckArea).to.equal("73"); + expect(response.attributes.deedDocumentPage).to.equal("74"); + expect(response.attributes.deedDocumentBook).to.equal("75"); + expect(response.attributes.deedDocumentNumber).to.equal("76"); + expect(response.attributes.deedOwnerFirstName).to.equal("77"); + expect(response.attributes.deedOwnerFirstName2).to.equal("78"); + expect(response.attributes.deedOwnerFirstName3).to.equal("79"); + expect(response.attributes.deedOwnerFirstName4).to.equal("80"); + expect(response.attributes.deedOwnerFullName).to.equal("81"); + expect(response.attributes.deedOwnerFullName2).to.equal("82"); + expect(response.attributes.deedOwnerFullName3).to.equal("83"); + expect(response.attributes.deedOwnerFullName4).to.equal("84"); + expect(response.attributes.deedOwnerLastName).to.equal("85"); + expect(response.attributes.deedOwnerLastName2).to.equal("86"); + expect(response.attributes.deedOwnerLastName3).to.equal("87"); + expect(response.attributes.deedOwnerLastName4).to.equal("88"); + expect(response.attributes.deedOwnerMiddleName).to.equal("89"); + expect(response.attributes.deedOwnerMiddleName2).to.equal("90"); + expect(response.attributes.deedOwnerMiddleName3).to.equal("91"); + expect(response.attributes.deedOwnerMiddleName4).to.equal("92"); + expect(response.attributes.deedOwnerSuffix).to.equal("93"); + expect(response.attributes.deedOwnerSuffix2).to.equal("94"); + expect(response.attributes.deedOwnerSuffix3).to.equal("95"); + expect(response.attributes.deedOwnerSuffix4).to.equal("96"); + expect(response.attributes.deedSaleDate).to.equal("97"); + expect(response.attributes.deedSalePrice).to.equal("98"); + expect(response.attributes.deedTransactionId).to.equal("99"); + expect(response.attributes.depthLinearFootage).to.equal("100"); + expect(response.attributes.disabledTaxExemption).to.equal("101"); + expect(response.attributes.drivewaySqft).to.equal("102"); + expect(response.attributes.drivewayType).to.equal("103"); + expect(response.attributes.effectiveYearBuilt).to.equal("104"); + expect(response.attributes.elevationFeet).to.equal("105"); + expect(response.attributes.elevator).to.equal("106"); + expect(response.attributes.equestrianArena).to.equal("107"); + expect(response.attributes.escalator).to.equal("108"); + expect(response.attributes.exerciseRoom).to.equal("109"); + expect(response.attributes.exteriorWalls).to.equal("110"); + expect(response.attributes.familyRoom).to.equal("111"); + expect(response.attributes.fence).to.equal("112"); + expect(response.attributes.fenceArea).to.equal("113"); + expect(response.attributes.fipsCode).to.equal("114"); + expect(response.attributes.fireResistanceCode).to.equal("115"); + expect(response.attributes.fireSprinklersFlag).to.equal("116"); + expect(response.attributes.fireplace).to.equal("117"); + expect(response.attributes.fireplaceNumber).to.equal("118"); + expect(response.attributes.firstName).to.equal("119"); + expect(response.attributes.firstName2).to.equal("120"); + expect(response.attributes.firstName3).to.equal("121"); + expect(response.attributes.firstName4).to.equal("122"); + expect(response.attributes.flooring).to.equal("123"); + expect(response.attributes.foundation).to.equal("124"); + expect(response.attributes.gameRoom).to.equal("125"); + expect(response.attributes.garage).to.equal("126"); + expect(response.attributes.garageSqft).to.equal("127"); + expect(response.attributes.gazebo).to.equal("128"); + expect(response.attributes.gazeboSqft).to.equal("129"); + expect(response.attributes.golfCourse).to.equal("130"); + expect(response.attributes.grainery).to.equal("131"); + expect(response.attributes.grainerySqft).to.equal("132"); + expect(response.attributes.greatRoom).to.equal("133"); + expect(response.attributes.greenhouse).to.equal("134"); + expect(response.attributes.greenhouseSqft).to.equal("135"); + expect(response.attributes.grossSqft).to.equal("136"); + expect(response.attributes.guesthouse).to.equal("137"); + expect(response.attributes.guesthouseSqft).to.equal("138"); + expect(response.attributes.handicapAccessibility).to.equal("139"); + expect(response.attributes.heat).to.equal("140"); + expect(response.attributes.heatFuelType).to.equal("141"); + expect(response.attributes.hobbyRoom).to.equal("142"); + expect(response.attributes.homeownerTaxExemption).to.equal("143"); + expect(response.attributes.instrumentDate).to.equal("144"); + expect(response.attributes.intercomSystem).to.equal("145"); + expect(response.attributes.interestRateType2).to.equal("146"); + expect(response.attributes.interiorStructure).to.equal("147"); + expect(response.attributes.kennel).to.equal("148"); + expect(response.attributes.kennelSqft).to.equal("149"); + expect(response.attributes.landUseCode).to.equal("150"); + expect(response.attributes.landUseGroup).to.equal("151"); + expect(response.attributes.landUseStandard).to.equal("152"); + expect(response.attributes.lastName).to.equal("153"); + expect(response.attributes.lastName2).to.equal("154"); + expect(response.attributes.lastName3).to.equal("155"); + expect(response.attributes.lastName4).to.equal("156"); + expect(response.attributes.latitude).to.equal("157"); + expect(response.attributes.laundry).to.equal("158"); + expect(response.attributes.leanTo).to.equal("159"); + expect(response.attributes.leanToSqft).to.equal("160"); + expect(response.attributes.legalDescription).to.equal("161"); + expect(response.attributes.legalUnit).to.equal("162"); + expect(response.attributes.lenderAddress).to.equal("163"); + expect(response.attributes.lenderAddress2).to.equal("164"); + expect(response.attributes.lenderCity).to.equal("165"); + expect(response.attributes.lenderCity2).to.equal("166"); + expect(response.attributes.lenderCode).to.equal("167"); + expect(response.attributes.lenderCode2).to.equal("168"); + expect(response.attributes.lenderFirstName).to.equal("169"); + expect(response.attributes.lenderFirstName2).to.equal("170"); + expect(response.attributes.lenderLastName).to.equal("171"); + expect(response.attributes.lenderLastName2).to.equal("172"); + expect(response.attributes.lenderName).to.equal("173"); + expect(response.attributes.lenderName2).to.equal("174"); + expect(response.attributes.lenderSellerCarryBack).to.equal("175"); + expect(response.attributes.lenderSellerCarryBack2).to.equal("176"); + expect(response.attributes.lenderState).to.equal("177"); + expect(response.attributes.lenderState2).to.equal("178"); + expect(response.attributes.lenderZip).to.equal("179"); + expect(response.attributes.lenderZip2).to.equal("180"); + expect(response.attributes.lenderZipExtended).to.equal("181"); + expect(response.attributes.lenderZipExtended2).to.equal("182"); + expect(response.attributes.loadingPlatform).to.equal("183"); + expect(response.attributes.loadingPlatformSqft).to.equal("184"); + expect(response.attributes.longitude).to.equal("185"); + expect(response.attributes.lot1).to.equal("186"); + expect(response.attributes.lot2).to.equal("187"); + expect(response.attributes.lot3).to.equal("188"); + expect(response.attributes.lotSqft).to.equal("189"); + expect(response.attributes.marketImprovementPercent).to.equal("190"); + expect(response.attributes.marketImprovementValue).to.equal("191"); + expect(response.attributes.marketLandValue).to.equal("192"); + expect(response.attributes.marketValueYear).to.equal("193"); + expect(response.attributes.matchType).to.equal("194"); + expect(response.attributes.mediaRoom).to.equal("195"); + expect(response.attributes.metroDivision).to.equal("196"); + expect(response.attributes.middleName).to.equal("197"); + expect(response.attributes.middleName2).to.equal("198"); + expect(response.attributes.middleName3).to.equal("199"); + expect(response.attributes.middleName4).to.equal("200"); + expect(response.attributes.milkhouse).to.equal("201"); + expect(response.attributes.milkhouseSqft).to.equal("202"); + expect(response.attributes.minorCivilDivisionCode).to.equal("203"); + expect(response.attributes.minorCivilDivisionName).to.equal("204"); + expect(response.attributes.mobileHomeHookup).to.equal("205"); + expect(response.attributes.mortgageAmount).to.equal("206"); + expect(response.attributes.mortgageAmount2).to.equal("207"); + expect(response.attributes.mortgageDueDate).to.equal("208"); + expect(response.attributes.mortgageDueDate2).to.equal("209"); + expect(response.attributes.mortgageInterestRate).to.equal("210"); + expect(response.attributes.mortgageInterestRateType).to.equal("211"); + expect(response.attributes.mortgageLenderCode).to.equal("212"); + expect(response.attributes.mortgageRate2).to.equal("213"); + expect(response.attributes.mortgageRecordingDate).to.equal("214"); + expect(response.attributes.mortgageRecordingDate2).to.equal("215"); + expect(response.attributes.mortgageTerm).to.equal("216"); + expect(response.attributes.mortgageTerm2).to.equal("217"); + expect(response.attributes.mortgageTermType).to.equal("218"); + expect(response.attributes.mortgageTermType2).to.equal("219"); + expect(response.attributes.mortgageType).to.equal("220"); + expect(response.attributes.mortgageType2).to.equal("221"); + expect(response.attributes.msaCode).to.equal("222"); + expect(response.attributes.msaName).to.equal("223"); + expect(response.attributes.mudRoom).to.equal("224"); + expect(response.attributes.multiParcelFlag).to.equal("225"); + expect(response.attributes.nameTitleCompany).to.equal("226"); + expect(response.attributes.neighborhoodCode).to.equal("227"); + expect(response.attributes.numberOfBuildings).to.equal("228"); + expect(response.attributes.office).to.equal("229"); + expect(response.attributes.officeSqft).to.equal("230"); + expect(response.attributes.otherTaxExemption).to.equal("231"); + expect(response.attributes.outdoorKitchenFireplace).to.equal("232"); + expect(response.attributes.overheadDoor).to.equal("233"); + expect(response.attributes.ownerFullName).to.equal("234"); + expect(response.attributes.ownerFullName2).to.equal("235"); + expect(response.attributes.ownerFullName3).to.equal("236"); + expect(response.attributes.ownerFullName4).to.equal("237"); + expect(response.attributes.ownerOccupancyStatus).to.equal("238"); + expect(response.attributes.ownershipTransferDate).to.equal("239"); + expect(response.attributes.ownershipTransferDocNumber).to.equal("240"); + expect(response.attributes.ownershipTransferTransactionId).to.equal("241"); + expect(response.attributes.ownershipType).to.equal("242"); + expect(response.attributes.ownershipType2).to.equal("243"); + expect(response.attributes.ownershipVestingRelationCode).to.equal("244"); + expect(response.attributes.parcelAccountNumber).to.equal("245"); + expect(response.attributes.parcelMapBook).to.equal("246"); + expect(response.attributes.parcelMapPage).to.equal("247"); + expect(response.attributes.parcelNumberAlternate).to.equal("248"); + expect(response.attributes.parcelNumberFormatted).to.equal("249"); + expect(response.attributes.parcelNumberPrevious).to.equal("250"); + expect(response.attributes.parcelNumberYearAdded).to.equal("251"); + expect(response.attributes.parcelNumberYearChange).to.equal("252"); + expect(response.attributes.parcelRawNumber).to.equal("253"); + expect(response.attributes.parcelShellRecord).to.equal("254"); + expect(response.attributes.parkingSpaces).to.equal("255"); + expect(response.attributes.patioArea).to.equal("256"); + expect(response.attributes.phaseName).to.equal("257"); + expect(response.attributes.plumbingFixturesCount).to.equal("257"); + expect(response.attributes.poleStruct).to.equal("258"); + expect(response.attributes.poleStructSqft).to.equal("259"); + expect(response.attributes.pond).to.equal("260"); + expect(response.attributes.pool).to.equal("261"); + expect(response.attributes.poolArea).to.equal("262"); + expect(response.attributes.poolhouse).to.equal("263"); + expect(response.attributes.poolhouseSqft).to.equal("264"); + expect(response.attributes.porch).to.equal("265"); + expect(response.attributes.porchArea).to.equal("266"); + expect(response.attributes.poultryHouse).to.equal("267"); + expect(response.attributes.poultryHouseSqft).to.equal("268"); + expect(response.attributes.previousAssessedValue).to.equal("269"); + expect(response.attributes.priorSaleAmount).to.equal("270"); + expect(response.attributes.priorSaleDate).to.equal("271"); + expect(response.attributes.propertyAddressCarrierRouteCode).to.equal("272"); + expect(response.attributes.propertyAddressCity).to.equal("273"); + expect(response.attributes.propertyAddressFull).to.equal("274"); + expect(response.attributes.propertyAddressHouseNumber).to.equal("275"); + expect(response.attributes.propertyAddressPostDirection).to.equal("276"); + expect(response.attributes.propertyAddressPreDirection).to.equal("277"); + expect(response.attributes.propertyAddressState).to.equal("278"); + expect(response.attributes.propertyAddressStreetName).to.equal("279"); + expect(response.attributes.propertyAddressStreetSuffix).to.equal("280"); + expect(response.attributes.propertyAddressUnitDesignator).to.equal("281"); + expect(response.attributes.propertyAddressUnitValue).to.equal("282"); + expect(response.attributes.propertyAddressZip4).to.equal("283"); + expect(response.attributes.propertyAddressZipcode).to.equal("284"); + expect(response.attributes.publicationDate).to.equal("285"); + expect(response.attributes.quarter).to.equal("286"); + expect(response.attributes.quarterQuarter).to.equal("287"); + expect(response.attributes.quonset).to.equal("288"); + expect(response.attributes.quonsetSqft).to.equal("289"); + expect(response.attributes.range).to.equal("290"); + expect(response.attributes.recordingDate).to.equal("291"); + expect(response.attributes.roofCover).to.equal("292"); + expect(response.attributes.roofFrame).to.equal("293"); + expect(response.attributes.rooms).to.equal("294"); + expect(response.attributes.rvParking).to.equal("295"); + expect(response.attributes.safeRoom).to.equal("296"); + expect(response.attributes.saleAmount).to.equal("297"); + expect(response.attributes.saleDate).to.equal("298"); + expect(response.attributes.sauna).to.equal("299"); + expect(response.attributes.section).to.equal("300"); + expect(response.attributes.securityAlarm).to.equal("301"); + expect(response.attributes.seniorTaxExemption).to.equal("302"); + expect(response.attributes.sewerType).to.equal("303"); + expect(response.attributes.shed).to.equal("304"); + expect(response.attributes.shedSqft).to.equal("305"); + expect(response.attributes.silo).to.equal("306"); + expect(response.attributes.siloSqft).to.equal("307"); + expect(response.attributes.sittingRoom).to.equal("308"); + expect(response.attributes.situsCounty).to.equal("309"); + expect(response.attributes.situsState).to.equal("310"); + expect(response.attributes.soundSystem).to.equal("311"); + expect(response.attributes.sportsCourt).to.equal("312"); + expect(response.attributes.sprinklers).to.equal("313"); + expect(response.attributes.stable).to.equal("314"); + expect(response.attributes.stableSqft).to.equal("315"); + expect(response.attributes.storageBuilding).to.equal("316"); + expect(response.attributes.storageBuildingSqft).to.equal("317"); + expect(response.attributes.storiesNumber).to.equal("318"); + expect(response.attributes.stormShelter).to.equal("319"); + expect(response.attributes.stormShutter).to.equal("320"); + expect(response.attributes.structureStyle).to.equal("321"); + expect(response.attributes.study).to.equal("322"); + expect(response.attributes.subdivision).to.equal("323"); + expect(response.attributes.suffix).to.equal("324"); + expect(response.attributes.suffix2).to.equal("325"); + expect(response.attributes.suffix3).to.equal("326"); + expect(response.attributes.suffix4).to.equal("327"); + expect(response.attributes.sunroom).to.equal("328"); + expect(response.attributes.taxAssessYear).to.equal("329"); + expect(response.attributes.taxBilledAmount).to.equal("330"); + expect(response.attributes.taxDelinquentYear).to.equal("331"); + expect(response.attributes.taxFiscalYear).to.equal("332"); + expect(response.attributes.taxJurisdiction).to.equal("333"); + expect(response.attributes.taxRateArea).to.equal("334"); + expect(response.attributes.tennisCourt).to.equal("335"); + expect(response.attributes.topographyCode).to.equal("336"); + expect(response.attributes.totalMarketValue).to.equal("337"); + expect(response.attributes.township).to.equal("338"); + expect(response.attributes.tractNumber).to.equal("339"); + expect(response.attributes.transferAmount).to.equal("340"); + expect(response.attributes.trustDescription).to.equal("341"); + expect(response.attributes.unitCount).to.equal("342"); + expect(response.attributes.upperFloorsSqft).to.equal("343"); + expect(response.attributes.utility).to.equal("344"); + expect(response.attributes.utilityBuilding).to.equal("345"); + expect(response.attributes.utilityBuildingSqft).to.equal("346"); + expect(response.attributes.utilitySqft).to.equal("347"); + expect(response.attributes.veteranTaxExemption).to.equal("348"); + expect(response.attributes.viewDescription).to.equal("349"); + expect(response.attributes.waterFeature).to.equal("350"); + expect(response.attributes.waterServiceType).to.equal("351"); + expect(response.attributes.wetBar).to.equal("352"); + expect(response.attributes.widowTaxExemption).to.equal("353"); + expect(response.attributes.widthLinearFootage).to.equal("354"); + expect(response.attributes.wineCellar).to.equal("355"); + expect(response.attributes.yearBuilt).to.equal("356"); + expect(response.attributes.zoning).to.equal("357"); + }); +}); diff --git a/tests/us_extract/test_Address.js b/tests/us_extract/test_Address.js deleted file mode 100644 index 8aad9f2..0000000 --- a/tests/us_extract/test_Address.js +++ /dev/null @@ -1,67 +0,0 @@ -const chai = require("chai"); -const expect = chai.expect; -const Address = require("../../src/us_extract/Address"); -const Candidate = require("../../src/us_street/Candidate"); - -describe("A US Extract Address", function () { - it("populates fields correctly.", function () { - let mockResponseAddress = { - "text": "5732 Lincoln Drive Minneapolis MN", - "verified": true, - "line": 4, - "start": 16, - "end": 49, - "api_output": [ - { - "candidate_index": 0, - "delivery_line_1": "5732 Lincoln Dr", - "last_line": "Minneapolis MN 55436-1608", - "delivery_point_barcode": "554361608327", - "components": { - "primary_number": "5732", - "street_name": "Lincoln", - "street_suffix": "Dr", - "city_name": "Minneapolis", - "state_abbreviation": "MN", - "zipcode": "55436", - "plus4_code": "1608", - "delivery_point": "32", - "delivery_point_check_digit": "7" - }, - "metadata": { - "record_type": "S", - "zip_type": "Standard", - "county_fips": "27053", - "county_name": "Hennepin", - "carrier_route": "C009", - "congressional_district": "03", - "rdi": "Commercial", - "elot_sequence": "0035", - "elot_sort": "A", - "latitude": 44.90127, - "longitude": -93.40045, - "precision": "Zip9", - "time_zone": "Central", - "utc_offset": -6, - "dst": true - }, - "analysis": { - "dpv_match_code": "Y", - "dpv_footnotes": "AABB", - "dpv_cmra": "N", - "dpv_vacant": "N", - "active": "Y", - "footnotes": "N#" - }, - }, - ], - }; - let address = new Address(mockResponseAddress); - expect(address.candidates[0]).to.be.an.instanceOf(Candidate); - expect(address.text).to.equal(mockResponseAddress.text); - expect(address.verified).to.equal(mockResponseAddress.verified); - expect(address.line).to.equal(mockResponseAddress.line); - expect(address.start).to.equal(mockResponseAddress.start); - expect(address.end).to.equal(mockResponseAddress.end); - }); -}); diff --git a/tests/us_extract/test_Address.ts b/tests/us_extract/test_Address.ts new file mode 100644 index 0000000..adfe84f --- /dev/null +++ b/tests/us_extract/test_Address.ts @@ -0,0 +1,66 @@ +import { expect } from "chai"; +import Address from "../../src/us_extract/Address.js"; +import Candidate from "../../src/us_street/Candidate.js"; + +describe("A US Extract Address", function () { + it("populates fields correctly.", function () { + let mockResponseAddress = { + text: "5732 Lincoln Drive Minneapolis MN", + verified: true, + line: 4, + start: 16, + end: 49, + api_output: [ + { + candidate_index: 0, + delivery_line_1: "5732 Lincoln Dr", + last_line: "Minneapolis MN 55436-1608", + delivery_point_barcode: "554361608327", + components: { + primary_number: "5732", + street_name: "Lincoln", + street_suffix: "Dr", + city_name: "Minneapolis", + state_abbreviation: "MN", + zipcode: "55436", + plus4_code: "1608", + delivery_point: "32", + delivery_point_check_digit: "7", + }, + metadata: { + record_type: "S", + zip_type: "Standard", + county_fips: "27053", + county_name: "Hennepin", + carrier_route: "C009", + congressional_district: "03", + rdi: "Commercial", + elot_sequence: "0035", + elot_sort: "A", + latitude: 44.90127, + longitude: -93.40045, + precision: "Zip9", + time_zone: "Central", + utc_offset: -6, + dst: true, + }, + analysis: { + dpv_match_code: "Y", + dpv_footnotes: "AABB", + dpv_cmra: "N", + dpv_vacant: "N", + active: "Y", + footnotes: "N#", + }, + }, + ], + }; + let address = new Address(mockResponseAddress); + expect(address.candidates[0]).to.be.an.instanceOf(Candidate); + expect(address.text).to.equal(mockResponseAddress.text); + expect(address.verified).to.equal(mockResponseAddress.verified); + expect(address.line).to.equal(mockResponseAddress.line); + expect(address.start).to.equal(mockResponseAddress.start); + expect(address.end).to.equal(mockResponseAddress.end); + }); +}); diff --git a/tests/us_extract/test_Client.js b/tests/us_extract/test_Client.ts similarity index 50% rename from tests/us_extract/test_Client.js rename to tests/us_extract/test_Client.ts index 2acc73d..cf893fb 100644 --- a/tests/us_extract/test_Client.js +++ b/tests/us_extract/test_Client.ts @@ -1,11 +1,9 @@ -const chai = require("chai"); -const expect = chai.expect; -const Client = require("../../src/us_extract/Client"); -const Lookup = require("../../src/us_extract/Lookup"); -const Result = require("../../src/us_extract/Result"); -const MockSender = require("../fixtures/mock_senders").MockSender; -const MockSenderWithResponse = require("../fixtures/mock_senders").MockSenderWithResponse; -const errors = require("../../src/Errors"); +import { expect } from "chai"; +import Client from "../../src/us_extract/Client.js"; +import Lookup from "../../src/us_extract/Lookup.js"; +import Result from "../../src/us_extract/Result.js"; +import { MockSender, MockSenderWithResponse } from "../fixtures/mock_senders.js"; +import errors from "../../src/Errors.js"; describe("A US Extract Client", function () { it("throws an error if sending without a lookup.", function () { @@ -44,9 +42,9 @@ describe("A US Extract Client", function () { let client = new Client(mockSender); const mockText = "Picard is coming back. All power to the engines."; let lookup = new Lookup(mockText); - lookup.html = 1; - lookup.aggressive = 2; - lookup.addressesHaveLineBreaks = 3; + lookup.html = 1 as any; + lookup.aggressive = 2 as any; + lookup.addressesHaveLineBreaks = 3 as any; lookup.addressesPerLine = 4; let expectedParams = { @@ -67,73 +65,75 @@ describe("A US Extract Client", function () { let client = new Client(mockSender); let lookup = new Lookup("Shine on you crazy diamond."); - return client.send(lookup).catch((e) => {expect(e).to.equal(expectedError);}); + return client.send(lookup).catch((e) => { + expect(e).to.equal(expectedError); + }); }); it("attaches result from a response to a lookup.", function () { const responseData = { - "meta": { - "lines": 6, - "unicode": false, - "address_count": 1, - "verified_count": 1, - "bytes": 53, - "character_count": 53 + meta: { + lines: 6, + unicode: false, + address_count: 1, + verified_count: 1, + bytes: 53, + character_count: 53, }, - "addresses": [ + addresses: [ { - "text": "5732 Lincoln Drive Minneapolis MN", - "verified": true, - "line": 4, - "start": 16, - "end": 49, - "api_output": [ + text: "5732 Lincoln Drive Minneapolis MN", + verified: true, + line: 4, + start: 16, + end: 49, + api_output: [ { - "candidate_index": 0, - "delivery_line_1": "5732 Lincoln Dr", - "last_line": "Minneapolis MN 55436-1608", - "delivery_point_barcode": "554361608327", - "components": { - "primary_number": "5732", - "street_name": "Lincoln", - "street_suffix": "Dr", - "city_name": "Minneapolis", - "state_abbreviation": "MN", - "zipcode": "55436", - "plus4_code": "1608", - "delivery_point": "32", - "delivery_point_check_digit": "7" + candidate_index: 0, + delivery_line_1: "5732 Lincoln Dr", + last_line: "Minneapolis MN 55436-1608", + delivery_point_barcode: "554361608327", + components: { + primary_number: "5732", + street_name: "Lincoln", + street_suffix: "Dr", + city_name: "Minneapolis", + state_abbreviation: "MN", + zipcode: "55436", + plus4_code: "1608", + delivery_point: "32", + delivery_point_check_digit: "7", + }, + metadata: { + record_type: "S", + zip_type: "Standard", + county_fips: "27053", + county_name: "Hennepin", + carrier_route: "C009", + congressional_district: "03", + rdi: "Commercial", + elot_sequence: "0035", + elot_sort: "A", + latitude: 44.90127, + longitude: -93.40045, + precision: "Zip9", + time_zone: "Central", + utc_offset: -6, + dst: true, }, - "metadata": { - "record_type": "S", - "zip_type": "Standard", - "county_fips": "27053", - "county_name": "Hennepin", - "carrier_route": "C009", - "congressional_district": "03", - "rdi": "Commercial", - "elot_sequence": "0035", - "elot_sort": "A", - "latitude": 44.90127, - "longitude": -93.40045, - "precision": "Zip9", - "time_zone": "Central", - "utc_offset": -6, - "dst": true + analysis: { + dpv_match_code: "Y", + dpv_footnotes: "AABB", + dpv_cmra: "N", + dpv_vacant: "N", + dpv_no_stat: "N", + active: "Y", + footnotes: "N#", }, - "analysis": { - "dpv_match_code": "Y", - "dpv_footnotes": "AABB", - "dpv_cmra": "N", - "dpv_vacant": "N", - "dpv_no_stat": "N", - "active": "Y", - "footnotes": "N#" - } - } - ] - } - ] + }, + ], + }, + ], }; let mockSender = new MockSenderWithResponse(responseData); @@ -141,8 +141,8 @@ describe("A US Extract Client", function () { let lookup = new Lookup("Sometimes when you're testing this field doesn't matter too much."); let expectedResult = new Result(responseData); - return client.send(lookup).then(response => { + return client.send(lookup).then((_response) => { expect(lookup.result).to.deep.equal(expectedResult); }); - }) -}); \ No newline at end of file + }); +}); diff --git a/tests/us_extract/test_Lookup.js b/tests/us_extract/test_Lookup.ts similarity index 81% rename from tests/us_extract/test_Lookup.js rename to tests/us_extract/test_Lookup.ts index ac65b0d..39a0682 100644 --- a/tests/us_extract/test_Lookup.js +++ b/tests/us_extract/test_Lookup.ts @@ -1,6 +1,5 @@ -const chai = require("chai"); -const expect = chai.expect; -const Lookup = require("../../src/us_extract/Lookup"); +import { expect } from "chai"; +import Lookup from "../../src/us_extract/Lookup.js"; describe("A US Extract Lookup", function () { it("correctly populates fields.", function () { @@ -16,4 +15,4 @@ describe("A US Extract Lookup", function () { expect(lookup.addressesHaveLineBreaks).to.equal(true); expect(lookup.addressesPerLine).to.equal(10); }); -}); \ No newline at end of file +}); diff --git a/tests/us_extract/test_Result.js b/tests/us_extract/test_Result.ts similarity index 52% rename from tests/us_extract/test_Result.js rename to tests/us_extract/test_Result.ts index 562e604..c7a88aa 100644 --- a/tests/us_extract/test_Result.js +++ b/tests/us_extract/test_Result.ts @@ -1,29 +1,28 @@ -const chai = require("chai"); -const expect = chai.expect; -const Result = require("../../src/us_extract/Result"); -const Address = require("../../src/us_extract/Address"); +import { expect } from "chai"; +import Result from "../../src/us_extract/Result.js"; +import Address from "../../src/us_extract/Address.js"; describe("A US Extract Result", function () { it("correctly populates fields.", function () { const mockResponseData = { - "meta": { - "lines": 6, - "unicode": false, - "address_count": 1, - "verified_count": 1, - "bytes": 53, - "character_count": 53, + meta: { + lines: 6, + unicode: false, + address_count: 1, + verified_count: 1, + bytes: 53, + character_count: 53, }, - "addresses": [ + addresses: [ { - "text": "5732 Lincoln Drive Minneapolis MN", - "verified": true, - "line": 4, - "start": 16, - "end": 49, - "api_output": [{}] - } - ] + text: "5732 Lincoln Drive Minneapolis MN", + verified: true, + line: 4, + start: 16, + end: 49, + api_output: [{}], + }, + ], }; let result = new Result(mockResponseData); diff --git a/tests/us_reverse_geo/test_Client.js b/tests/us_reverse_geo/test_Client.js deleted file mode 100644 index e720e29..0000000 --- a/tests/us_reverse_geo/test_Client.js +++ /dev/null @@ -1,48 +0,0 @@ -const chai = require("chai"); -const expect = chai.expect; -const Client = require("../../src/us_reverse_geo/Client"); -const Lookup = require("../../src/us_reverse_geo/Lookup"); -const MockSender = require("../fixtures/mock_senders").MockSender; -const MockSenderWithResponse = require("../fixtures/mock_senders").MockSenderWithResponse; -const Response = require("../../src/us_reverse_geo/Response"); - -describe("A US Reverse Geo client", function () { - it("has an inner sender.", function () { - let mockSender = new MockSender(); - let client = new Client(mockSender); - - expect(client.sender).to.deep.equal(mockSender); - }); - - - it("attaches a result from a response to a lookup.", function () { - const expectedMockPayload = { - "results": [ - { - "coordinate": { - "latitude": 40.111111, - "longitude": -111.111111, - "accuracy": "Rooftop", - "license": "SmartyStreets" - }, - "distance": 2.7207432, - "address": { - "street": "2335 S State St", - "city": "Provo", - "state_abbreviation": "UT", - "zipcode": "84606", - "source": "postal" - } - }, - ] - }; - let mockSender = new MockSenderWithResponse(expectedMockPayload); - const client = new Client(mockSender); - let lookup = new Lookup(44.888888888, -111.111111111, "postal"); - - return client.send(lookup).then(() => { - expect(lookup.response).to.deep.equal(expectedMockPayload); - expect(lookup.response).to.be.an.instanceOf(Response); - }); - }); -}); diff --git a/tests/us_reverse_geo/test_Client.ts b/tests/us_reverse_geo/test_Client.ts new file mode 100644 index 0000000..80cebc1 --- /dev/null +++ b/tests/us_reverse_geo/test_Client.ts @@ -0,0 +1,59 @@ +import { expect } from "chai"; +import Client from "../../src/us_reverse_geo/Client.js"; +import Lookup from "../../src/us_reverse_geo/Lookup.js"; +import { MockSenderWithResponse } from "../fixtures/mock_senders.js"; +import Response from "../../src/us_reverse_geo/Response.js"; + +describe("A US Reverse Geo client", function () { + it("attaches a result from a response to a lookup.", function () { + const mockPayload = { + results: [ + { + coordinate: { + latitude: 40.111111, + longitude: -111.111111, + accuracy: "Rooftop", + license: 1, + }, + distance: 2.7207432, + address: { + street: "2335 S State St", + city: "Provo", + state_abbreviation: "UT", + zipcode: "84606", + source: "postal", + }, + }, + ], + }; + const expectedResult = { + results: [ + { + coordinate: { + latitude: 40.111111, + longitude: -111.111111, + accuracy: "Rooftop", + license: "SmartyStreets Proprietary", + }, + distance: 2.7207432, + address: { + street: "2335 S State St", + city: "Provo", + stateAbbreviation: "UT", + zipcode: "84606", + source: "postal", + smartyKey: undefined, + }, + }, + ], + }; + let mockSender = new MockSenderWithResponse(mockPayload); + const client = new Client(mockSender); + let lookup = new Lookup(44.888888888, -111.111111111, "postal"); + + return client.send(lookup).then(() => { + expect(lookup.response).to.deep.equal(expectedResult); + expect(lookup.response).to.be.an.instanceOf(Response); + }); + }); +}); diff --git a/tests/us_reverse_geo/test_Lookup.js b/tests/us_reverse_geo/test_Lookup.ts similarity index 67% rename from tests/us_reverse_geo/test_Lookup.js rename to tests/us_reverse_geo/test_Lookup.ts index 0787306..d5d6f09 100644 --- a/tests/us_reverse_geo/test_Lookup.js +++ b/tests/us_reverse_geo/test_Lookup.ts @@ -1,14 +1,13 @@ -const chai = require("chai"); -const expect = chai.expect; -const Lookup = require("../../src/us_reverse_geo/Lookup"); +import { expect } from "chai"; +import Lookup from "../../src/us_reverse_geo/Lookup.js"; describe("A US Reverse Geo lookup", function () { it("correctly populates fields.", function () { let lookup = new Lookup(44.888888888, -111.111111111, "postal"); - expect(lookup.source).to.equal("postal") + expect(lookup.source).to.equal("postal"); expect(lookup.latitude).to.equal("44.88888889"); expect(lookup.longitude).to.equal("-111.11111111"); expect(lookup.response.results).to.deep.equal([]); }); -}); \ No newline at end of file +}); diff --git a/tests/us_reverse_geo/test_Response.js b/tests/us_reverse_geo/test_Response.ts similarity index 81% rename from tests/us_reverse_geo/test_Response.js rename to tests/us_reverse_geo/test_Response.ts index 4068632..51cc5a5 100644 --- a/tests/us_reverse_geo/test_Response.js +++ b/tests/us_reverse_geo/test_Response.ts @@ -1,6 +1,5 @@ -const chai = require("chai"); -const expect = chai.expect; -const Response = require("../../src/us_reverse_geo/Response"); +import { expect } from "chai"; +import Response from "../../src/us_reverse_geo/Response.js"; describe("A US Reverse Geo match response", function () { it("populates with the appropriate fields.", function () { @@ -11,7 +10,7 @@ describe("A US Reverse Geo match response", function () { latitude: 1.1, longitude: 2.2, accuracy: "3", - license: 1 + license: 1, }, distance: 4.4, address: { @@ -19,10 +18,10 @@ describe("A US Reverse Geo match response", function () { city: "6", state_abbreviation: "7", zipcode: "8", - source: "postal" - } + source: "postal", + }, }, - ] + ], }; const response = new Response(sampleResponse); @@ -32,7 +31,7 @@ describe("A US Reverse Geo match response", function () { let address = result.address; expect(address.street).to.equal("5"); expect(address.city).to.equal("6"); - expect(address.state_abbreviation).to.equal("7"); + expect(address.stateAbbreviation).to.equal("7"); expect(address.zipcode).to.equal("8"); expect(address.source).to.equal("postal"); let coordinate = result.coordinate; diff --git a/tests/us_street/test_Candidate.js b/tests/us_street/test_Candidate.ts similarity index 65% rename from tests/us_street/test_Candidate.js rename to tests/us_street/test_Candidate.ts index 2bfd515..1563bf2 100644 --- a/tests/us_street/test_Candidate.js +++ b/tests/us_street/test_Candidate.ts @@ -1,6 +1,5 @@ -const chai = require("chai"); -const expect = chai.expect; -const Candidate = require("../../src/us_street/Candidate"); +import { expect } from "chai"; +import Candidate from "../../src/us_street/Candidate.js"; describe("A match candidate", function () { it("has populated fields.", function () { @@ -51,8 +50,8 @@ describe("A match candidate", function () { precision: "38", time_zone: "39", utc_offset: 40.0, - dst: "41", - ews_match: "47", + dst: true, + ews_match: true, }, analysis: { dpv_match_code: "42", @@ -63,24 +62,24 @@ describe("A match candidate", function () { footnotes: "48", lacslink_code: "49", lacslink_indicator: "50", - suitelink_match: "51", + suitelink_match: true, dpv_no_stat: "52", enhanced_match: "53", components: { - primary_number: "54", - street_predirection: "55", - street_name: "56", - street_postdirection: "57", - street_suffix: "58", - secondary_number: "59", - secondary_designator: "60", - extra_secondary_number: "61", - extra_secondary_designator: "62", - city_name: "63", - state_abbreviation: "64", - zipcode: "65", - plus4_code: "66", - urbanization: "67", + primary_number: { status: "54", change: ["a"] }, + street_predirection: { status: "55", change: ["b"] }, + street_name: { status: "56", change: ["c"] }, + street_postdirection: { status: "57", change: ["d"] }, + street_suffix: { status: "58", change: ["e"] }, + secondary_number: { status: "59", change: ["f"] }, + secondary_designator: { status: "60", change: ["g"] }, + extra_secondary_number: { status: "61", change: ["h"] }, + extra_secondary_designator: { status: "62", change: ["i"] }, + city_name: { status: "63", change: ["j"] }, + state_abbreviation: { status: "64", change: ["k"] }, + zipcode: { status: "65", change: ["l"] }, + plus4_code: { status: "66", change: ["m"] }, + urbanization: { status: "67", change: ["n"] }, }, }, }; @@ -131,8 +130,8 @@ describe("A match candidate", function () { expect(candidate.metadata.precision).to.equal("38"); expect(candidate.metadata.timeZone).to.equal("39"); expect(candidate.metadata.utcOffset).to.equal(40.0); - expect(candidate.metadata.obeysDst).to.equal("41"); - expect(candidate.metadata.isEwsMatch).to.equal("47"); + expect(candidate.metadata.obeysDst).to.equal(true); + expect(candidate.metadata.isEwsMatch).to.equal(true); expect(candidate.analysis.dpvMatchCode).to.equal("42"); expect(candidate.analysis.dpvFootnotes).to.equal("43"); @@ -142,23 +141,53 @@ describe("A match candidate", function () { expect(candidate.analysis.footnotes).to.equal("48"); expect(candidate.analysis.lacsLinkCode).to.equal("49"); expect(candidate.analysis.lacsLinkIndicator).to.equal("50"); - expect(candidate.analysis.isSuiteLinkMatch).to.equal("51"); + expect(candidate.analysis.isSuiteLinkMatch).to.equal(true); expect(candidate.analysis.noStat).to.equal("52"); expect(candidate.analysis.enhancedMatch).to.equal("53"); - expect(candidate.analysis.components.primaryNumber).to.equal("54"); - expect(candidate.analysis.components.streetPredirection).to.equal("55"); - expect(candidate.analysis.components.streetName).to.equal("56"); - expect(candidate.analysis.components.streetPostdirection).to.equal("57"); - expect(candidate.analysis.components.streetSuffix).to.equal("58"); - expect(candidate.analysis.components.secondaryNumber).to.equal("59"); - expect(candidate.analysis.components.secondaryDesignator).to.equal("60"); - expect(candidate.analysis.components.extraSecondaryNumber).to.equal("61"); - expect(candidate.analysis.components.extraSecondaryDesignator).to.equal("62"); - expect(candidate.analysis.components.cityName).to.equal("63"); - expect(candidate.analysis.components.stateAbbreviation).to.equal("64"); - expect(candidate.analysis.components.zipCode).to.equal("65"); - expect(candidate.analysis.components.plus4Code).to.equal("66"); - expect(candidate.analysis.components.urbanization).to.equal("67"); + expect(candidate.analysis.components.primaryNumber).to.deep.equal({ + status: "54", + change: ["a"], + }); + expect(candidate.analysis.components.streetPredirection).to.deep.equal({ + status: "55", + change: ["b"], + }); + expect(candidate.analysis.components.streetName).to.deep.equal({ status: "56", change: ["c"] }); + expect(candidate.analysis.components.streetPostdirection).to.deep.equal({ + status: "57", + change: ["d"], + }); + expect(candidate.analysis.components.streetSuffix).to.deep.equal({ + status: "58", + change: ["e"], + }); + expect(candidate.analysis.components.secondaryNumber).to.deep.equal({ + status: "59", + change: ["f"], + }); + expect(candidate.analysis.components.secondaryDesignator).to.deep.equal({ + status: "60", + change: ["g"], + }); + expect(candidate.analysis.components.extraSecondaryNumber).to.deep.equal({ + status: "61", + change: ["h"], + }); + expect(candidate.analysis.components.extraSecondaryDesignator).to.deep.equal({ + status: "62", + change: ["i"], + }); + expect(candidate.analysis.components.cityName).to.deep.equal({ status: "63", change: ["j"] }); + expect(candidate.analysis.components.stateAbbreviation).to.deep.equal({ + status: "64", + change: ["k"], + }); + expect(candidate.analysis.components.zipCode).to.deep.equal({ status: "65", change: ["l"] }); + expect(candidate.analysis.components.plus4Code).to.deep.equal({ status: "66", change: ["m"] }); + expect(candidate.analysis.components.urbanization).to.deep.equal({ + status: "67", + change: ["n"], + }); }); }); diff --git a/tests/us_street/test_Client.js b/tests/us_street/test_Client.ts similarity index 79% rename from tests/us_street/test_Client.js rename to tests/us_street/test_Client.ts index 703000c..f3dfc60 100644 --- a/tests/us_street/test_Client.js +++ b/tests/us_street/test_Client.ts @@ -1,25 +1,21 @@ -const chai = require("chai"); -const expect = chai.expect; -const Client = require("../../src/us_street/Client"); -const Lookup = require("../../src/us_street/Lookup"); -const Candidate = require("../../src/us_street/Candidate"); -const Batch = require("../../src/Batch"); -const errors = require("../../src/Errors"); -const MockSender = require("../fixtures/mock_senders").MockSender; -const MockSenderWithResponse = require("../fixtures/mock_senders").MockSenderWithResponse; +import { expect } from "chai"; +import Client from "../../src/us_street/Client.js"; +import Lookup from "../../src/us_street/Lookup.js"; +import Candidate from "../../src/us_street/Candidate.js"; +import Batch from "../../src/Batch.js"; +import errors from "../../src/Errors.js"; +import { MockSender, MockSenderWithResponse } from "../fixtures/mock_senders.js"; describe("A US Street client", function () { it("calls its inner sender's send function.", function () { const mockSender = { - send: function (request) { + send: function (_request: any) { sentFlag = true; - mockSenderRequest = request; - } + }, }; - const client = new Client(mockSender); + const client = new Client(mockSender as any); let lookup = new Lookup(); let sentFlag = false; - let mockSenderRequest = {}; client.send(lookup); @@ -29,7 +25,7 @@ describe("A US Street client", function () { it("builds a request for a single lookup with the correct request parameters.", function () { let mockSender = new MockSender(); const client = new Client(mockSender); - let lookup = new Lookup("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"); + let lookup = new Lookup("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11" as any, "12"); let expectedParameters = { street: "1", street2: "2", @@ -181,7 +177,6 @@ describe("A US Street client", function () { let lookup = new Lookup(); lookup.street = "123 Main St"; lookup.match = "invalid"; - // maxCandidates left undefined - should NOT default to 5 for non-enhanced let expectedParameters = { street: "123 Main St", match: "invalid", @@ -217,24 +212,24 @@ describe("A US Street client", function () { }); it("attaches a match candidate from a response to a lookup.", function () { - const expectedMockPayload = [{delivery_line_1: "An address", input_index: 0}]; + const expectedMockPayload = [{ delivery_line_1: "An address", input_index: 0 }]; let mockSender = new MockSenderWithResponse(expectedMockPayload); const client = new Client(mockSender); let lookup = new Lookup(); - let expectedResult = new Candidate({delivery_line_1: "An address", input_index: 0}); + let expectedResult = new Candidate({ delivery_line_1: "An address", input_index: 0 }); - return client.send(lookup).then(response => { + return client.send(lookup).then((_response) => { expect(lookup.result[0]).to.deep.equal(expectedResult); }); }); it("attaches match candidates to their corresponding lookups.", function () { - const expectedMockPayload = JSON.stringify([ - {delivery_line_1: "Address 0", input_index: 0}, - {delivery_line_1: "Alternate address 0", input_index: 0}, - {delivery_line_1: "Address 1", input_index: 1}, - {delivery_line_1: "Address 3", input_index: 3}, - ]); + const expectedMockPayload = [ + { delivery_line_1: "Address 0", input_index: 0 }, + { delivery_line_1: "Alternate address 0", input_index: 0 }, + { delivery_line_1: "Address 1", input_index: 1 }, + { delivery_line_1: "Address 3", input_index: 3 }, + ]; let mockSender = new MockSenderWithResponse(expectedMockPayload); let client = new Client(mockSender); let lookup0 = new Lookup(); @@ -248,12 +243,13 @@ describe("A US Street client", function () { batch.add(lookup2); batch.add(lookup3); - client.send(batch).then(response => { - expect(batch.getByIndex(0).result[0].deliveryLine1).to.equal("Address 0"); - expect(batch.getByIndex(0).result[1].deliveryLine1).to.equal("Alternate address 0"); - expect(batch.getByIndex(1).result[0].deliveryLine1).to.equal("Address 1"); - expect(batch.getByIndex(2).result).to.deep.equal([]); - expect(batch.getByIndex(3).result[0].deliveryLine1).to.equal("Address 3"); + return client.send(batch).then((_response) => { + const get = (i: number) => batch.getByIndex(i) as Lookup; + expect(get(0).result[0].deliveryLine1).to.equal("Address 0"); + expect(get(0).result[1].deliveryLine1).to.equal("Alternate address 0"); + expect(get(1).result[0].deliveryLine1).to.equal("Address 1"); + expect(get(2).result).to.deep.equal([]); + expect(get(3).result[0].deliveryLine1).to.equal("Address 3"); }); }); @@ -263,14 +259,16 @@ describe("A US Street client", function () { let client = new Client(mockSender); let lookup = new Lookup(); - return client.send(lookup).catch((e) => {expect(e).to.equal(expectedMockError);}); + return client.send(lookup).catch((e) => { + expect(e).to.equal(expectedMockError); + }); }); it("throws an exception if a lookup is undefined.", function () { let mockSender = new MockSender(); let client = new Client(mockSender); - expect(() => client.send()).to.throw(errors.UndefinedLookupError); + expect(() => (client.send as any)()).to.throw(errors.UndefinedLookupError); }); it("attaches request parameters for batches with a single lookup and a request payload for batches with more than 1 lookup.", function () { diff --git a/tests/us_street/test_Lookup.js b/tests/us_street/test_Lookup.ts similarity index 63% rename from tests/us_street/test_Lookup.js rename to tests/us_street/test_Lookup.ts index 08c3a3f..92ebb06 100644 --- a/tests/us_street/test_Lookup.js +++ b/tests/us_street/test_Lookup.ts @@ -1,10 +1,23 @@ -const chai = require("chai"); -const expect = chai.expect; -const Lookup = require("../../src/us_street/Lookup"); +import { expect } from "chai"; +import Lookup from "../../src/us_street/Lookup.js"; -describe ("A US Street lookup", function () { - it ("correctly populates fields.", function () { - const lookup = new Lookup("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m"); +describe("A US Street lookup", function () { + it("correctly populates fields.", function () { + const lookup = new Lookup( + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k" as any, + "l", + "m", + ); expect(lookup.street).to.equal("a"); expect(lookup.street2).to.equal("b"); @@ -21,9 +34,9 @@ describe ("A US Street lookup", function () { expect(lookup.format).to.equal("m"); }); - it ("has a result array.", function () { + it("has a result array.", function () { const lookup = new Lookup(); expect(Array.isArray(lookup.result)).to.equal(true); }); -}); \ No newline at end of file +}); diff --git a/tests/us_zipcode/test_Client.js b/tests/us_zipcode/test_Client.ts similarity index 65% rename from tests/us_zipcode/test_Client.js rename to tests/us_zipcode/test_Client.ts index e1e74a9..9b28813 100644 --- a/tests/us_zipcode/test_Client.js +++ b/tests/us_zipcode/test_Client.ts @@ -1,27 +1,22 @@ -let chai = require("chai"); -const expect = chai.expect; -const Client = require("../../src/us_zipcode/Client"); -const Lookup = require("../../src/us_zipcode/Lookup"); -const Result = require("../../src/us_zipcode/Result"); -const Batch = require("../../src/Batch"); -const errors = require("../../src/Errors"); -const MockSender = require("../fixtures/mock_senders").MockSender; -const MockSenderWithResponse = require("../fixtures/mock_senders").MockSenderWithResponse; +import { expect } from "chai"; +import Client from "../../src/us_zipcode/Client.js"; +import Lookup from "../../src/us_zipcode/Lookup.js"; +import Result from "../../src/us_zipcode/Result.js"; +import Batch from "../../src/Batch.js"; +import errors from "../../src/Errors.js"; +import { MockSender, MockSenderWithResponse } from "../fixtures/mock_senders.js"; describe("A US Zipcode client", function () { it("calls its inner sender's send function.", function () { const mockSender = { - send: function (request) { + send: function (_request: any) { sentFlag = true; - mockSenderRequest = request; - return new Promise((resolve, reject) => { - }); - } + return new Promise((_resolve) => {}); + }, }; - const client = new Client(mockSender); + const client = new Client(mockSender as any); let lookup = new Lookup(); let sentFlag = false; - let mockSenderRequest = {}; client.send(lookup); @@ -43,11 +38,7 @@ describe("A US Zipcode client", function () { let lookup1 = new Lookup("lookup1"); let lookup2 = new Lookup("lookup2"); let batch = new Batch(); - const expectedPayload = [ - {"city": "lookup0"}, - {"city": "lookup1"}, - {"city": "lookup2"} - ]; + const expectedPayload = [{ city: "lookup0" }, { city: "lookup1" }, { city: "lookup2" }]; batch.add(lookup0); batch.add(lookup1); @@ -59,24 +50,24 @@ describe("A US Zipcode client", function () { }); it("attaches a match candidate from a response to a lookup.", function () { - const expectedMockPayload = [{input_index: 0}]; + const expectedMockPayload = [{ input_index: 0 }]; let mockSender = new MockSenderWithResponse(expectedMockPayload); const client = new Client(mockSender); let lookup = new Lookup(); - let expectedResult = new Result({input_index: 0}); + let expectedResult = new Result({ input_index: 0 }); - return client.send(lookup).then(response => { + return client.send(lookup).then((_response) => { expect(lookup.result[0]).to.deep.equal(expectedResult); }); }); it("attaches match candidates to their corresponding lookups.", function () { - const expectedMockPayload = JSON.stringify([ - {city: "City 0", input_index: 0}, - {city: "Alternate city 0", input_index: 0}, - {city: "City 1", input_index: 1}, - {city: "City 3", input_index: 3}, - ]); + const expectedMockPayload = [ + { status: "Status 0", input_index: 0 }, + { status: "Alternate status 0", input_index: 0 }, + { status: "Status 1", input_index: 1 }, + { status: "Status 3", input_index: 3 }, + ]; let mockSender = new MockSenderWithResponse(expectedMockPayload); let client = new Client(mockSender); let lookup0 = new Lookup(); @@ -90,12 +81,13 @@ describe("A US Zipcode client", function () { batch.add(lookup2); batch.add(lookup3); - client.send(batch).then(response => { - expect(batch.getByIndex(0).result[0].city).to.equal("City 0"); - expect(batch.getByIndex(0).result[1].city).to.equal("Alternate city 0"); - expect(batch.getByIndex(1).result[0].city).to.equal("City 1"); - expect(batch.getByIndex(2).result).to.deep.equal([]); - expect(batch.getByIndex(3).result[0].city).to.equal("City 3"); + return client.send(batch).then((_response) => { + const get = (i: number) => batch.getByIndex(i) as Lookup; + expect(get(0).result[0].status).to.equal("Status 0"); + expect(get(0).result[1].status).to.equal("Alternate status 0"); + expect(get(1).result[0].status).to.equal("Status 1"); + expect(get(2).result).to.deep.equal([]); + expect(get(3).result[0].status).to.equal("Status 3"); }); }); @@ -123,14 +115,16 @@ describe("A US Zipcode client", function () { let client = new Client(mockSender); let lookup = new Lookup(); - return client.send(lookup).catch((e) => {expect(e).to.equal(expectedMockError);}); + return client.send(lookup).catch((e) => { + expect(e).to.equal(expectedMockError); + }); }); it("throws an exception if a lookup is undefined.", function () { let mockSender = new MockSender(); let client = new Client(mockSender); - expect(() => client.send()).to.throw(errors.UndefinedLookupError); + expect(() => (client.send as any)()).to.throw(errors.UndefinedLookupError); }); it("builds a request for a single lookup with the correct request parameters.", function () { diff --git a/tests/us_zipcode/test_Result.js b/tests/us_zipcode/test_Result.js deleted file mode 100644 index 08fbb7a..0000000 --- a/tests/us_zipcode/test_Result.js +++ /dev/null @@ -1,81 +0,0 @@ -const chai = require("chai"); -const expect = chai.expect; -const Result = require("../../src/us_zipcode/Result"); - -describe("A US Zipcode result", function () { - it("populates accurately on a valid lookup.", function () { - let sampleResponse = { - "input_index": 0, - "city_states": [ - { - "city": "1", - "state_abbreviation": "2", - "state": "3", - "mailable_city": "4" - } - ], - "zipcodes": [ - { - "zipcode": "5", - "zipcode_type": "6", - "default_city": "7", - "county_fips": "8", - "county_name": "9", - "latitude": 10, - "longitude": 11, - "precision": "12", - "alternate_counties": [ - { - "county_fips": "13", - "county_name": "14", - "state_abbreviation": "15", - "state": "16" - } - ], - "state_abbreviation": "17", - "state": "18" - } - ] - }; - let result = new Result(sampleResponse); - - expect(result.inputIndex).to.equal(0); - expect(result.status).to.equal(undefined); - expect(result.reason).to.equal(undefined); - - expect(result.cities[0].city).to.equal('1'); - expect(result.cities[0].stateAbbreviation).to.equal('2'); - expect(result.cities[0].state).to.equal('3'); - expect(result.cities[0].mailableCity).to.equal('4'); - - expect(result.zipcodes[0].zipcode).to.equal('5'); - expect(result.zipcodes[0].zipcodeType).to.equal('6'); - expect(result.zipcodes[0].defaultCity).to.equal('7'); - expect(result.zipcodes[0].countyFips).to.equal('8'); - expect(result.zipcodes[0].countyName).to.equal('9'); - expect(result.zipcodes[0].latitude).to.equal(10); - expect(result.zipcodes[0].longitude).to.equal(11); - expect(result.zipcodes[0].precision).to.equal('12'); - expect(result.zipcodes[0].alternateCounties[0].countyFips).to.equal('13'); - expect(result.zipcodes[0].alternateCounties[0].countyName).to.equal('14'); - expect(result.zipcodes[0].alternateCounties[0].stateAbbreviation).to.equal('15'); - expect(result.zipcodes[0].alternateCounties[0].state).to.equal('16'); - expect(result.zipcodes[0].stateAbbreviation).to.equal('17'); - expect(result.zipcodes[0].state).to.equal('18'); - - expect(result.valid).to.equal(true); - }); - - it("populates accurately on an invalid lookup", function () { - let sampleResponse = { - "status": "testing_status", - "reason": "We are testing." - }; - - let result = new Result(sampleResponse); - - expect(result.status).to.equal("testing_status"); - expect(result.reason).to.equal("We are testing."); - - }); -}); \ No newline at end of file diff --git a/tests/us_zipcode/test_Result.ts b/tests/us_zipcode/test_Result.ts new file mode 100644 index 0000000..81bf493 --- /dev/null +++ b/tests/us_zipcode/test_Result.ts @@ -0,0 +1,79 @@ +import { expect } from "chai"; +import Result from "../../src/us_zipcode/Result.js"; + +describe("A US Zipcode result", function () { + it("populates accurately on a valid lookup.", function () { + let sampleResponse = { + input_index: 0, + city_states: [ + { + city: "1", + state_abbreviation: "2", + state: "3", + mailable_city: true, + }, + ], + zipcodes: [ + { + zipcode: "5", + zipcode_type: "6", + default_city: "7", + county_fips: "8", + county_name: "9", + latitude: 10, + longitude: 11, + precision: "12", + alternate_counties: [ + { + county_fips: "13", + county_name: "14", + state_abbreviation: "15", + state: "16", + }, + ], + state_abbreviation: "17", + state: "18", + }, + ], + }; + let result = new Result(sampleResponse); + + expect(result.inputIndex).to.equal(0); + expect(result.status).to.equal(undefined); + expect(result.reason).to.equal(undefined); + + expect(result.cities[0].city).to.equal("1"); + expect(result.cities[0].stateAbbreviation).to.equal("2"); + expect(result.cities[0].state).to.equal("3"); + expect(result.cities[0].mailableCity).to.equal(true); + + expect(result.zipcodes[0].zipcode).to.equal("5"); + expect(result.zipcodes[0].zipcodeType).to.equal("6"); + expect(result.zipcodes[0].defaultCity).to.equal("7"); + expect(result.zipcodes[0].countyFips).to.equal("8"); + expect(result.zipcodes[0].countyName).to.equal("9"); + expect(result.zipcodes[0].latitude).to.equal(10); + expect(result.zipcodes[0].longitude).to.equal(11); + expect(result.zipcodes[0].precision).to.equal("12"); + expect(result.zipcodes[0].alternateCounties[0].countyFips).to.equal("13"); + expect(result.zipcodes[0].alternateCounties[0].countyName).to.equal("14"); + expect(result.zipcodes[0].alternateCounties[0].stateAbbreviation).to.equal("15"); + expect(result.zipcodes[0].alternateCounties[0].state).to.equal("16"); + expect(result.zipcodes[0].stateAbbreviation).to.equal("17"); + expect(result.zipcodes[0].state).to.equal("18"); + + expect(result.valid).to.equal(true); + }); + + it("populates accurately on an invalid lookup", function () { + let sampleResponse = { + status: "testing_status", + reason: "We are testing.", + }; + + let result = new Result(sampleResponse); + + expect(result.status).to.equal("testing_status"); + expect(result.reason).to.equal("We are testing."); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index ea5d2a6..f08e793 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,6 @@ "paths": { "@/*": ["./*"] }, - "allowJs": true, "alwaysStrict": true, "exactOptionalPropertyTypes": true, "noPropertyAccessFromIndexSignature": true, @@ -32,9 +31,9 @@ "isolatedModules": true, "jsx": "preserve", "types": ["mocha", "chai", "node"], - "importHelpers": false, - "target": "es2015" - }, - "include": ["src/**/*", "tests/**/*"], + "importHelpers": false, + "target": "es2015" + }, + "include": ["index.ts", "src/**/*", "tests/**/*"], "exclude": ["node_modules"] }