44 changed files with 3063 additions and 153 deletions
@ -1,10 +1,124 @@ |
|||
|
|||
<div class="row"> |
|||
<div class="col-12 col-sm-6 col-md-4 border"> |
|||
<div id="map"></div> |
|||
<div class="col-12"> |
|||
<div class="section-title">Contatti</div> |
|||
</div> |
|||
|
|||
<div class="col-12 col-sm-6 col-md-8 border"> |
|||
a |
|||
<div class="col-12 col-sm-12 col-md-7 contacts"> |
|||
<i class="fa fa-map-marker"></i> <b>Sede:</b> Via Settimio Mobilio, 17 - SALERNO<br> |
|||
<i class="fa fa-phone"></i> <b>Telefono:</b> 089.405080 - 089.795900<br> |
|||
<i class="fa fa-fax"></i> <b>Fax:</b> 089.798628<br> |
|||
<i class="fa fa-envelope"></i> <b>E-Mail:</b> info@ordinefarmacistisalerno.it<br> |
|||
<i class="fa fa-envelope"></i> <b>E-Mail certificata:</b> ordinefarmacistisa@pec.fofi.it <br> |
|||
</div> |
|||
|
|||
<div class="col-12 col-sm-12 col-md-5 mb-2"> |
|||
<div id="map"> |
|||
<iframe width="100%" height="100%" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.it/maps?f=q&source=s_q&hl=it&geocode=&q=ordine+farmacisti+salerno&sll=41.442726,12.392578&sspn=17.04957,43.286133&ie=UTF8&hq=ordine+farmacisti&hnear=Salerno+SA&ll=40.685389,14.781933&spn=0.004012,0.014656&z=14&iwloc=A&cid=4099829483191197382&output=embed"></iframe> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
<div class="row last-news"> |
|||
|
|||
<div class="col-12"> |
|||
<div class="section-title">Ultime notizie</div> |
|||
|
|||
<p class="item"><a href=""><span class="date">07-12-2017 </span> - Chiusura Uffici sabato 9</a></p> |
|||
<p class="item"><a href=""><span class="date">07-12-2017 </span> - Chiusura Uffici sabato 9</a></p> |
|||
<p class="item"><a href=""><span class="date">07-12-2017 </span> - Chiusura Uffici sabato 9</a></p> |
|||
<p class="item"><a href=""><span class="date">07-12-2017 </span> - Chiusura Uffici sabato 9</a></p> |
|||
</div> |
|||
|
|||
<div class="col-12 my-2"> |
|||
<p class="text-right"><a class="font-12" href="">Vai a tutte le news <i class="fa fa-angle-right"></i></a></p> |
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
|
|||
<div class="row p-3"> |
|||
<div class="col-12 col-sm-4 col-md-3 spot"> |
|||
<div class="content"> |
|||
<a href="#"> |
|||
<div class="title">Piazza pitagora</div> |
|||
<img src="http://unsplash.it/800/600"> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-12 col-sm-4 col-md-3 spot"> |
|||
<div class="content"> |
|||
<a href="#"> |
|||
<div class="title">Dipartimento di Farmacia</div> |
|||
<img src="http://unsplash.it/800/608"> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-12 col-sm-4 col-md-3 spot"> |
|||
<div class="content"> |
|||
<a href="#"> |
|||
<div class="title">Forum degli iscritti</div> |
|||
<img src="http://unsplash.it/800/607"> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-12 col-sm-4 col-md-3 spot"> |
|||
<div class="content"> |
|||
<a href="#"> |
|||
<div class="title">F.O.F.I.</div> |
|||
<img src="http://unsplash.it/800/606"> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-12 col-sm-4 col-md-3 spot"> |
|||
<div class="content"> |
|||
<a href="#"> |
|||
<div class="title">ASSO.FA.N.T.</div> |
|||
<img src="http://unsplash.it/800/605"> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-12 col-sm-4 col-md-3 spot"> |
|||
<div class="content"> |
|||
<a href="#"> |
|||
<div class="title">E.N.P.A.F.</div> |
|||
<img src="http://unsplash.it/800/604"> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-12 col-sm-4 col-md-3 spot"> |
|||
<div class="content"> |
|||
<a href="#"> |
|||
<div class="title">Federfarma</div> |
|||
<img src="http://unsplash.it/800/603"> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-12 col-sm-4 col-md-3 spot"> |
|||
<div class="content"> |
|||
<a href="#"> |
|||
<div class="title">Università di Salerno</div> |
|||
<img src="http://unsplash.it/800/602"> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-12 col-sm-4 col-md-3 spot"> |
|||
<div class="content"> |
|||
<a href="#"> |
|||
<div class="title">Storia dell'Ordine</div> |
|||
<img src="http://unsplash.it/800/601"> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
|
|||
</div> |
|||
|
@ -1,11 +1,85 @@ |
|||
|
|||
<div class="col-12 col-sm-12 col-md-2 p-0"> |
|||
<div class="col-12 col-sm-3 col-md-12 banner"></div> |
|||
<div class="col-12 col-sm-3 col-md-12 banner"></div> |
|||
<div class="col-12 col-sm-3 col-md-12 banner"></div> |
|||
<div class="col-12 col-sm-3 col-md-12 banner"></div> |
|||
<div class="col-12 col-sm-3 col-md-12 banner"></div> |
|||
<div class="col-12 col-sm-3 col-md-12 banner"></div> |
|||
<div class="col-12 col-sm-3 col-md-12 banner"></div> |
|||
<div class="col-12 col-sm-3 col-md-12 banner"></div> |
|||
<div class="banner"> |
|||
<div class="content"> |
|||
<a href="#"> |
|||
<div class="title">Piazza pitagora</div> |
|||
<img src="http://unsplash.it/800/600"> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="banner"> |
|||
<div class="content"> |
|||
<a href="#"> |
|||
<div class="title">Dipartimento di Farmacia</div> |
|||
<img src="http://unsplash.it/800/608"> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="banner"> |
|||
<div class="content"> |
|||
<a href="#"> |
|||
<div class="title">Forum degli iscritti</div> |
|||
<img src="http://unsplash.it/800/607"> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="banner"> |
|||
<div class="content"> |
|||
<a href="#"> |
|||
<div class="title">F.O.F.I.</div> |
|||
<img src="http://unsplash.it/800/606"> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="banner"> |
|||
<div class="content"> |
|||
<a href="#"> |
|||
<div class="title">ASSO.FA.N.T.</div> |
|||
<img src="http://unsplash.it/800/605"> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="banner"> |
|||
<div class="content"> |
|||
<a href="#"> |
|||
<div class="title">E.N.P.A.F.</div> |
|||
<img src="http://unsplash.it/800/604"> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="banner"> |
|||
<div class="content"> |
|||
<a href="#"> |
|||
<div class="title">Federfarma</div> |
|||
<img src="http://unsplash.it/800/603"> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="banner"> |
|||
<div class="content"> |
|||
<a href="#"> |
|||
<div class="title">Università di Salerno</div> |
|||
<img src="http://unsplash.it/800/602"> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="banner"> |
|||
<div class="content"> |
|||
<a href="#"> |
|||
<div class="title">Storia dell'Ordine</div> |
|||
<img src="http://unsplash.it/800/601"> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
|
|||
</div> |
|||
|
@ -0,0 +1 @@ |
|||
../@google/maps/bin/run.js |
@ -0,0 +1,201 @@ |
|||
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. |
|||
|
|||
To apply the Apache License to your work, attach the following |
|||
boilerplate notice, with the fields enclosed by brackets "{}" |
|||
replaced with your own identifying information. (Don't include |
|||
the brackets!) The text should be enclosed in the appropriate |
|||
comment syntax for the file format. We also recommend that a |
|||
file or class name and description of purpose be included on the |
|||
same "printed page" as the copyright notice for easier |
|||
identification within third-party archives. |
|||
|
|||
Copyright {yyyy} {name of copyright owner} |
|||
|
|||
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. |
@ -0,0 +1,163 @@ |
|||
Node.js Client for Google Maps Services |
|||
======================================= |
|||
|
|||
Use Node.js? Want to [geocode][Geocoding API] something? Looking |
|||
for [directions][Directions API]? |
|||
This library brings the [Google Maps API Web Services] to your Node.js |
|||
application.  |
|||
|
|||
The Node.js Client for Google Maps Services is a Node.js Client library |
|||
for the following Google Maps APIs: |
|||
|
|||
- [Directions API] |
|||
- [Distance Matrix API] |
|||
- [Elevation API] |
|||
- [Geocoding API] |
|||
- [Places API] |
|||
- [Roads API] |
|||
- [Time Zone API] |
|||
|
|||
Keep in mind that the same [terms and conditions](https://developers.google.com/maps/terms) |
|||
apply to usage of the APIs when they're accessed through this library. |
|||
|
|||
## Features |
|||
|
|||
- **Retry on Failure** Automatically retry when intermittent failures occur. |
|||
That is, when any of the retryable 5xx errors are returned from the API. |
|||
|
|||
- **Rate-limiting** Requests are rate-limited by the client, which helps |
|||
prevent reaching the server-enforced rate limit. |
|||
|
|||
## Quick Start |
|||
|
|||
$ npm install @google/maps |
|||
|
|||
**Note:** You'll need to have npm 2.7.0 or greater installed, since this library is hosted as a |
|||
[scoped package](https://docs.npmjs.com/getting-started/scoped-packages). |
|||
|
|||
Create a new client object by calling `createClient()` |
|||
|
|||
```js |
|||
var googleMapsClient = require('@google/maps').createClient({ |
|||
key: 'your API key here' |
|||
}); |
|||
``` |
|||
|
|||
Make requests to the Google Maps APIs by calling methods on the client object. |
|||
|
|||
```js |
|||
// Geocode an address. |
|||
googleMapsClient.geocode({ |
|||
address: '1600 Amphitheatre Parkway, Mountain View, CA' |
|||
}, function(err, response) { |
|||
if (!err) { |
|||
console.log(response.json.results); |
|||
} |
|||
}); |
|||
``` |
|||
|
|||
For more usage examples, check out [the tests](spec/e2e/). |
|||
|
|||
View the [reference documentation](https://googlemaps.github.io/google-maps-services-js/docs/) |
|||
|
|||
Additional documentation for the included web services is available at |
|||
https://developers.google.com/maps/. |
|||
|
|||
## API keys |
|||
|
|||
Each Google Maps Web Service request requires an API key or client ID. API keys |
|||
are freely available with a Google Account at |
|||
https://developers.google.com/console. The type of API key you need is a |
|||
**Server key**. |
|||
|
|||
To get an API key: |
|||
|
|||
1. Visit https://developers.google.com/console and log in with |
|||
a Google Account. |
|||
1. Select one of your existing projects, or create a new project. |
|||
1. Enable the API(s) you want to use. The Node.js Client for Google Maps Services |
|||
accesses the following APIs: |
|||
* Directions API |
|||
* Distance Matrix API |
|||
* Elevation API |
|||
* Geocoding API |
|||
* Places API |
|||
* Roads API |
|||
* Time Zone API |
|||
1. Create a new **Server key**. |
|||
1. If you'd like to restrict requests to a specific IP address, do so now. |
|||
|
|||
For guided help, follow the instructions for the [Directions API][directions-key]. You only need one API key, but |
|||
remember to enable all the APIs you need. |
|||
For even more information, see the guide to [API keys][apikey]. |
|||
|
|||
When you have an API key, you can create a client object: |
|||
|
|||
```js |
|||
var googleMapsClient = require('@google/maps').createClient({ |
|||
key: 'your API key here' |
|||
}); |
|||
``` |
|||
|
|||
### Client IDs |
|||
|
|||
Google Maps APIs Premium Plan customers can use their [client ID and secret][clientid] to authenticate, |
|||
instead of an API key. |
|||
|
|||
```js |
|||
var googleMapsClient = require('@google/maps').createClient({ |
|||
clientId: 'Add your client ID here', |
|||
clientSecret: 'Add your client secret here', |
|||
}); |
|||
``` |
|||
|
|||
**Important:** This key should be kept secret on your server. |
|||
|
|||
## Developing |
|||
|
|||
In order to run the end-to-end tests, you'll need to supply your API key via an |
|||
environment variable. |
|||
|
|||
$ export GOOGLE_MAPS_API_KEY=AIza-your-api-key |
|||
$ npm test |
|||
|
|||
## Support |
|||
|
|||
This library is community supported. We're comfortable enough with the |
|||
stability and features of the library that we want you to build real |
|||
production applications on it. We will try to support, through Stack |
|||
Overflow, the public surface of the library and maintain |
|||
backwards compatibility in the future; however, while the library is in |
|||
version 0.x, we reserve the right to make backwards-incompatible |
|||
changes. If we do remove some functionality (typically because better |
|||
functionality exists or if the feature proved infeasible), our intention |
|||
is to deprecate and give developers a year to update their code. |
|||
|
|||
If you find a bug, or have a feature suggestion, please |
|||
[log an issue][issues]. If you'd like to contribute, please read |
|||
[How to Contribute][contrib]. |
|||
|
|||
## Command-line Interface |
|||
|
|||
Installing via npm also provides the `googlemaps` command-line utility, |
|||
which can then be used to pipe JSON results to other command-line programs: |
|||
|
|||
``` |
|||
$ googlemaps directions --origin 'Sydney Town Hall' --destination 'Parramatta, NSW' |
|||
``` |
|||
|
|||
[apikey]: https://developers.google.com/maps/faq#keysystem |
|||
[clientid]: https://developers.google.com/maps/documentation/business/webservices/auth |
|||
|
|||
[Google Maps API Web Services]: https://developers.google.com/maps/documentation/webservices/ |
|||
[Directions API]: https://developers.google.com/maps/documentation/directions/ |
|||
[directions-key]: https://developers.google.com/maps/documentation/directions/get-api-key#key |
|||
[Distance Matrix API]: https://developers.google.com/maps/documentation/distancematrix/ |
|||
[Elevation API]: https://developers.google.com/maps/documentation/elevation/ |
|||
[Geocoding API]: https://developers.google.com/maps/documentation/geocoding/ |
|||
[Time Zone API]: https://developers.google.com/maps/documentation/timezone/ |
|||
[Roads API]: https://developers.google.com/maps/documentation/roads/ |
|||
[Places API]: https://developers.google.com/places/web-service/ |
|||
|
|||
[issues]: https://github.com/googlemaps/google-maps-services-js/issues |
|||
[contrib]: https://github.com/googlemaps/google-maps-services-js/blob/master/CONTRIBUTING.md |
@ -0,0 +1,28 @@ |
|||
#!/usr/bin/env node
|
|||
|
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/ |
|||
|
|||
var lib = require('@google/maps'); |
|||
var args = process.argv.slice(3); |
|||
var apiCall = lib.createClient()[process.argv[2]]; |
|||
|
|||
try { |
|||
apiCall(lib.cli.parseArgs(args), lib.cli.callback); |
|||
} catch (error) { |
|||
console.log("Error:", error.message); |
|||
} |
@ -0,0 +1,94 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/; |
|||
|
|||
var utils = require('../internal/convert'); |
|||
var v = require('../internal/validate'); |
|||
|
|||
/** |
|||
* Makes a directions request. |
|||
* |
|||
* @name GoogleMapsClient#directions |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {LatLng} query.origin |
|||
* @param {LatLng} query.destination |
|||
* @param {string} [query.mode] |
|||
* @param {LatLng[]} [query.waypoints] |
|||
* @param {boolean} [query.alternatives] |
|||
* @param {string[]} [query.avoid] |
|||
* @param {string} [query.language] |
|||
* @param {string} [query.units] |
|||
* @param {string} [query.region] |
|||
* @param {Date|number} [query.departure_time] |
|||
* @param {Date|number} [query.arrival_time] |
|||
* @param {string} [query.traffic_model] |
|||
* @param {string[]} [query.transit_mode] |
|||
* @param {string} [query.transit_routing_preference] |
|||
* @param {boolean} [query.optimize] |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.directions = { |
|||
url: 'https://maps.googleapis.com/maps/api/directions/json', |
|||
validator: v.compose([ |
|||
v.mutuallyExclusiveProperties(['arrival_time', 'departure_time']), |
|||
v.object({ |
|||
origin: utils.latLng, |
|||
destination: utils.latLng, |
|||
mode: v.optional(v.oneOf([ |
|||
'driving', 'walking', 'bicycling', 'transit' |
|||
])), |
|||
waypoints: v.optional(utils.pipedArrayOf(utils.latLng)), |
|||
alternatives: v.optional(v.boolean), |
|||
avoid: v.optional(utils.pipedArrayOf(v.oneOf([ |
|||
'tolls', 'highways', 'ferries', 'indoor' |
|||
]))), |
|||
language: v.optional(v.string), |
|||
units: v.optional(v.oneOf(['metric', 'imperial'])), |
|||
region: v.optional(v.string), |
|||
departure_time: v.optional(utils.timeStamp), |
|||
arrival_time: v.optional(utils.timeStamp), |
|||
traffic_model: v.optional(v.oneOf([ |
|||
'best_guess', 'pessimistic', 'optimistic' |
|||
])), |
|||
transit_mode: v.optional(utils.pipedArrayOf(v.oneOf([ |
|||
'bus', 'subway', 'train', 'tram', 'rail' |
|||
]))), |
|||
transit_routing_preference: v.optional(v.oneOf([ |
|||
'less_walking', 'fewer_transfers' |
|||
])), |
|||
optimize: v.optional(v.boolean), |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}), |
|||
function(query) { |
|||
if (query.waypoints && query.optimize) { |
|||
query.waypoints = 'optimize:true|' + query.waypoints; |
|||
} |
|||
delete query.optimize; |
|||
|
|||
if (query.waypoints && query.mode === 'transit') { |
|||
throw new v.InvalidValueError('cannot specify waypoints with transit'); |
|||
} |
|||
|
|||
if (query.traffic_model && !query.departure_time) { |
|||
throw new v.InvalidValueError('traffic_model requires departure_time'); |
|||
} |
|||
return query; |
|||
} |
|||
]) |
|||
}; |
@ -0,0 +1,72 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/; |
|||
|
|||
var utils = require('../internal/convert'); |
|||
var v = require('../internal/validate'); |
|||
|
|||
/** |
|||
* Makes a distance matrix request. |
|||
* |
|||
* @name GoogleMapsClient#distanceMatrix |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {LatLng[]} query.origins |
|||
* @param {LatLng[]} query.destinations |
|||
* @param {string} [query.mode] |
|||
* @param {string} [query.language] |
|||
* @param {string[]} [query.avoid] |
|||
* @param {string} [query.units] |
|||
* @param {Date|number} [query.departure_time] |
|||
* @param {Date|number} [query.arrival_time] |
|||
* @param {string[]} [query.transit_mode] |
|||
* @param {string} [query.transit_routing_preference] |
|||
* @param {string} [query.traffic_model] |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.distanceMatrix = { |
|||
url: 'https://maps.googleapis.com/maps/api/distancematrix/json', |
|||
validator: v.compose([ |
|||
v.mutuallyExclusiveProperties(['arrival_time', 'departure_time']), |
|||
v.object({ |
|||
origins: utils.pipedArrayOf(utils.latLng), |
|||
destinations: utils.pipedArrayOf(utils.latLng), |
|||
mode: v.optional(v.oneOf([ |
|||
'driving', 'walking', 'bicycling', 'transit' |
|||
])), |
|||
language: v.optional(v.string), |
|||
region: v.optional(v.string), |
|||
avoid: v.optional(utils.pipedArrayOf(v.oneOf([ |
|||
'tolls', 'highways', 'ferries', 'indoor' |
|||
]))), |
|||
units: v.optional(v.oneOf(['metric', 'imperial'])), |
|||
departure_time: v.optional(utils.timeStamp), |
|||
arrival_time: v.optional(utils.timeStamp), |
|||
transit_mode: v.optional(utils.pipedArrayOf(v.oneOf([ |
|||
'bus', 'subway', 'train', 'tram', 'rail' |
|||
]))), |
|||
transit_routing_preference: v.optional(v.oneOf([ |
|||
'less_walking', 'fewer_transfers' |
|||
])), |
|||
traffic_model: v.optional(v.oneOf([ |
|||
'best_guess', 'pessimistic', 'optimistic' |
|||
])), |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}) |
|||
]) |
|||
}; |
@ -0,0 +1,65 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/; |
|||
|
|||
var utils = require('../internal/convert'); |
|||
var v = require('../internal/validate'); |
|||
|
|||
/** |
|||
* Makes an elevation request. |
|||
* |
|||
* @name GoogleMapsClient#elevation |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {LatLng[]} query.locations |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.elevation = { |
|||
url: 'https://maps.googleapis.com/maps/api/elevation/json', |
|||
validator: v.object({ |
|||
locations: utils.pipedArrayOf(utils.latLng), |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}) |
|||
}; |
|||
|
|||
/** |
|||
* Makes an elevation-along-path request. |
|||
* |
|||
* @name GoogleMapsClient#elevationAlongPath |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {LatLng[]|string} query.path |
|||
* @param {number} query.samples |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.elevationAlongPath = { |
|||
url: 'https://maps.googleapis.com/maps/api/elevation/json', |
|||
validator: v.object({ |
|||
path: function(path) { |
|||
if (typeof path == 'string') { |
|||
return 'enc:' + path; |
|||
} else { |
|||
return utils.pipedArrayOf(utils.latLng)(path); |
|||
} |
|||
}, |
|||
samples: v.number, |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}) |
|||
}; |
@ -0,0 +1,84 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/; |
|||
|
|||
var utils = require('../internal/convert'); |
|||
var v = require('../internal/validate'); |
|||
|
|||
/** |
|||
* Makes a geocode request. |
|||
* |
|||
* @name GoogleMapsClient#geocode |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {string} [query.address] |
|||
* @param {Object} [query.components] |
|||
* @param {Object} [query.bounds] |
|||
* @param {number} query.bounds.south |
|||
* @param {number} query.bounds.west |
|||
* @param {number} query.bounds.north |
|||
* @param {number} query.bounds.east |
|||
* @param {string} [query.region] |
|||
* @param {string} [query.language] |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.geocode = { |
|||
url: 'https://maps.googleapis.com/maps/api/geocode/json', |
|||
validator: v.object({ |
|||
address: v.optional(v.string), |
|||
components: v.optional(utils.pipedKeyValues), |
|||
bounds: v.optional(utils.bounds), |
|||
region: v.optional(v.string), |
|||
language: v.optional(v.string), |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}) |
|||
}; |
|||
|
|||
/** |
|||
* Makes a reverse geocode request. |
|||
* |
|||
* @name GoogleMapsClient#reverseGeocode |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {LatLng} [query.latlng] |
|||
* @param {string} [query.place_id] |
|||
* @param {string} [query.result_type] |
|||
* @param {string} [query.location_type] |
|||
* @param {string} [query.language] |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.reverseGeocode = { |
|||
url: 'https://maps.googleapis.com/maps/api/geocode/json', |
|||
validator: v.compose([ |
|||
v.mutuallyExclusiveProperties(['place_id', 'latlng']), |
|||
v.mutuallyExclusiveProperties(['place_id', 'result_type']), |
|||
v.mutuallyExclusiveProperties(['place_id', 'location_type']), |
|||
v.object({ |
|||
latlng: v.optional(utils.latLng), |
|||
place_id: v.optional(v.string), |
|||
result_type: v.optional(utils.pipedArrayOf(v.string)), |
|||
location_type: v.optional(utils.pipedArrayOf(v.oneOf([ |
|||
'ROOFTOP', 'RANGE_INTERPOLATED', 'GEOMETRIC_CENTER', 'APPROXIMATE' |
|||
]))), |
|||
language: v.optional(v.string), |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}) |
|||
]) |
|||
}; |
@ -0,0 +1,76 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2017 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/ |
|||
|
|||
var utils = require('../internal/convert'); |
|||
var v = require('../internal/validate'); |
|||
|
|||
/** |
|||
* Makes a geolocation request. |
|||
* |
|||
* For a detailed guide, see https://developers.google.com/maps/documentation/geolocation/intro
|
|||
* |
|||
* @name GoogleMapsClient#geolocate |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {number} [query.homeMobileCountryCode] |
|||
* @param {number} [query.homeMobileNetworkCode] |
|||
* @param {string} [query.radioType] |
|||
* @param {string} [query.carrier] |
|||
* @param {boolean} [query.considerIp] |
|||
* @param {Object[]} [query.cellTowers] |
|||
* @param {Object[]} [query.wifiAccessPoints] |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.geolocate = { |
|||
url: 'https://www.googleapis.com/geolocation/v1/geolocate', |
|||
options: { |
|||
method: 'POST', |
|||
headers: {'content-type': 'application/json;'}, |
|||
canRetry: function(response) { |
|||
return response.status === 403; |
|||
}, |
|||
isSuccessful: function(response) { |
|||
return response.status === 200 || response.status === 404; |
|||
} |
|||
}, |
|||
validator: v.object({ |
|||
homeMobileCountryCode: v.optional(v.number), |
|||
homeMobileNetworkCode: v.optional(v.number), |
|||
radioType: v.optional(v.string), |
|||
carrier: v.optional(v.string), |
|||
considerIp: v.optional(v.boolean), |
|||
cellTowers: v.optional(v.array(v.object({ |
|||
cellId: v.number, |
|||
locationAreaCode: v.number, |
|||
mobileCountryCode: v.number, |
|||
mobileNetworkCode: v.number, |
|||
age: v.optional(v.number), |
|||
signalStrength: v.optional(v.number), |
|||
timingAdvance: v.optional(v.number) |
|||
}))), |
|||
wifiAccessPoints: v.optional(v.array(v.object({ |
|||
macAddress: v.string, |
|||
signalStrength: v.optional(v.number), |
|||
age: v.optional(v.number), |
|||
channel: v.optional(v.number), |
|||
signalToNoiseRatio: v.optional(v.number) |
|||
}))), |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}) |
|||
}; |
@ -0,0 +1,233 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/; |
|||
|
|||
var utils = require('../internal/convert'); |
|||
var v = require('../internal/validate'); |
|||
|
|||
/** |
|||
* Makes a places request. |
|||
* |
|||
* @name GoogleMapsClient#places |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {string} query.query |
|||
* @param {string} [query.language] |
|||
* @param {LatLng} [query.location] |
|||
* @param {number} [query.radius] |
|||
* @param {number} [query.minprice] |
|||
* @param {number} [query.maxprice] |
|||
* @param {boolean} [query.opennow] |
|||
* @param {string} [query.type] |
|||
* @param {string} [query.pagetoken] |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.places = { |
|||
url: 'https://maps.googleapis.com/maps/api/place/textsearch/json', |
|||
validator: v.object({ |
|||
query: v.optional(v.string), |
|||
language: v.optional(v.string), |
|||
location: v.optional(utils.latLng), |
|||
radius: v.optional(v.number), |
|||
minprice: v.optional(v.number), |
|||
maxprice: v.optional(v.number), |
|||
opennow: v.optional(v.boolean), |
|||
type: v.optional(v.string), |
|||
pagetoken: v.optional(v.string), |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}) |
|||
}; |
|||
|
|||
/** |
|||
* Makes a nearby places request. |
|||
* |
|||
* @name GoogleMapsClient#placesNearby |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {LatLng} query.location |
|||
* @param {string} [query.language] |
|||
* @param {number} [query.radius] |
|||
* @param {string} [query.keyword] |
|||
* @param {number} [query.minprice] |
|||
* @param {number} [query.maxprice] |
|||
* @param {string} [query.name] |
|||
* @param {boolean} [query.opennow] |
|||
* @param {string} [query.rankby] Either 'prominence' or 'distance' |
|||
* @param {string} [query.type] |
|||
* @param {string} [query.pagetoken] |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.placesNearby = { |
|||
url: 'https://maps.googleapis.com/maps/api/place/nearbysearch/json', |
|||
validator: v.object({ |
|||
location: utils.latLng, |
|||
language: v.optional(v.string), |
|||
radius: v.optional(v.number), |
|||
keyword: v.optional(v.string), |
|||
minprice: v.optional(v.number), |
|||
maxprice: v.optional(v.number), |
|||
name: v.optional(v.string), |
|||
opennow: v.optional(v.boolean), |
|||
rankby: v.optional(v.oneOf(['prominence', 'distance'])), |
|||
type: v.optional(v.string), |
|||
pagetoken: v.optional(v.string), |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}) |
|||
}; |
|||
|
|||
/** |
|||
* Makes a places radar search request. |
|||
* |
|||
* @name GoogleMapsClient#placesRadar |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {LatLng} query.location |
|||
* @param {number} query.radius |
|||
* @param {string} [query.language] |
|||
* @param {string} [query.keyword] |
|||
* @param {number} [query.minprice] |
|||
* @param {number} [query.maxprice] |
|||
* @param {string} [query.name] |
|||
* @param {boolean} [query.opennow] |
|||
* @param {string} [query.type] |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.placesRadar = { |
|||
url: 'https://maps.googleapis.com/maps/api/place/radarsearch/json', |
|||
validator: v.object({ |
|||
location: utils.latLng, |
|||
radius: v.number, |
|||
language: v.optional(v.string), |
|||
keyword: v.optional(v.string), |
|||
minprice: v.optional(v.number), |
|||
maxprice: v.optional(v.number), |
|||
name: v.optional(v.string), |
|||
opennow: v.optional(v.boolean), |
|||
type: v.optional(v.string), |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}) |
|||
}; |
|||
|
|||
/** |
|||
* Makes a place detail request. |
|||
* |
|||
* @name GoogleMapsClient#place |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {string} query.placeid |
|||
* @param {string} [query.language] |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.place = { |
|||
url: 'https://maps.googleapis.com/maps/api/place/details/json', |
|||
validator: v.object({ |
|||
placeid: v.string, |
|||
language: v.optional(v.string), |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}) |
|||
}; |
|||
|
|||
/** |
|||
* Makes a place photos request. |
|||
* |
|||
* @name GoogleMapsClient#placesPhoto |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {string} query.photoreference |
|||
* @param {number} [query.maxwidth] |
|||
* @param {number} [query.maxheight] |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.placesPhoto = { |
|||
url: 'https://maps.googleapis.com/maps/api/place/photo', |
|||
validator: v.object({ |
|||
photoreference: v.string, |
|||
maxwidth: v.optional(v.number), |
|||
maxheight: v.optional(v.number), |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}) |
|||
}; |
|||
|
|||
/** |
|||
* Makes a places autocomplete request. |
|||
* |
|||
* @name GoogleMapsClient#placesAutoComplete |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {string} query.input |
|||
* @param {number} [query.offset] |
|||
* @param {LatLng} [query.location] |
|||
* @param {string} [query.language] |
|||
* @param {number} [query.radius] |
|||
* @param {string} [query.types] |
|||
* @param {Array<string>} [query.components] |
|||
* @param {boolean} [query.strictbounds] |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.placesAutoComplete = { |
|||
url: 'https://maps.googleapis.com/maps/api/place/autocomplete/json', |
|||
validator: v.object({ |
|||
input: v.string, |
|||
offset: v.optional(v.number), |
|||
location: v.optional(utils.latLng), |
|||
language: v.optional(v.string), |
|||
radius: v.optional(v.number), |
|||
types: v.optional(v.oneOf(['geocode', 'address', 'establishment', '(regions)', '(cities)'])), |
|||
components: v.optional(utils.pipedKeyValues), |
|||
strictbounds: v.optional(v.boolean), |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}) |
|||
}; |
|||
|
|||
|
|||
/** |
|||
* Makes a places query autocomplete request. |
|||
* |
|||
* @name GoogleMapsClient#placesQueryAutoComplete |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {string} query.input |
|||
* @param {number} [query.offset] |
|||
* @param {LatLng} [query.location] |
|||
* @param {string} [query.language] |
|||
* @param {number} [query.radius] |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.placesQueryAutoComplete = { |
|||
url: 'https://maps.googleapis.com/maps/api/place/queryautocomplete/json', |
|||
validator: v.object({ |
|||
input: v.string, |
|||
offset: v.optional(v.number), |
|||
location: v.optional(utils.latLng), |
|||
language: v.optional(v.string), |
|||
radius: v.optional(v.number), |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}) |
|||
}; |
@ -0,0 +1,106 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/; |
|||
|
|||
var utils = require('../internal/convert'); |
|||
var v = require('../internal/validate'); |
|||
|
|||
/** |
|||
* Makes a snap-to-roads request. |
|||
* |
|||
* @name GoogleMapsClient#snapToRoads |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {LatLng[]} query.path |
|||
* @param {boolean} [query.interpolate] |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.snapToRoads = { |
|||
url: 'https://roads.googleapis.com/v1/snapToRoads', |
|||
supportsClientId: false, |
|||
validator: v.object({ |
|||
path: utils.pipedArrayOf(utils.latLng), |
|||
interpolate: v.optional(v.boolean), |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}) |
|||
}; |
|||
|
|||
/** |
|||
* Makes a nearest roads request. |
|||
* |
|||
* @name GoogleMapsClient#nearestRoads |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {LatLng[]} query.points |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.nearestRoads = { |
|||
url: 'https://roads.googleapis.com/v1/nearestRoads', |
|||
supportsClientId: false, |
|||
validator: v.object({ |
|||
points: utils.pipedArrayOf(utils.latLng), |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}) |
|||
}; |
|||
|
|||
/** |
|||
* Makes a speed-limits request for a place ID. For speed-limits |
|||
* requests using a path parameter, use the snappedSpeedLimits method. |
|||
* |
|||
* @name GoogleMapsClient#speedLimits |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {string[]} query.placeId |
|||
* @param {string} [query.units] Either 'KPH' or 'MPH' |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.speedLimits = { |
|||
url: 'https://roads.googleapis.com/v1/speedLimits', |
|||
supportsClientId: false, |
|||
validator: v.object({ |
|||
placeId: v.array(v.string), |
|||
units: v.optional(v.oneOf(['KPH', 'MPH'])), |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}) |
|||
}; |
|||
|
|||
/** |
|||
* Makes a speed-limits request for a path. |
|||
* |
|||
* @name GoogleMapsClient#snappedSpeedLimits |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {LatLng[]} query.path |
|||
* @param {string} [query.units] Either 'KPH' or 'MPH' |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.snappedSpeedLimits = { |
|||
url: 'https://roads.googleapis.com/v1/speedLimits', |
|||
supportsClientId: false, |
|||
validator: v.object({ |
|||
path: utils.pipedArrayOf(utils.latLng), |
|||
units: v.optional(v.oneOf(['KPH', 'MPH'])), |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}) |
|||
}; |
@ -0,0 +1,42 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/; |
|||
|
|||
var utils = require('../internal/convert'); |
|||
var v = require('../internal/validate'); |
|||
|
|||
/** |
|||
* Makes a timezone request. |
|||
* |
|||
* @name GoogleMapsClient#timezone |
|||
* @function |
|||
* @param {Object} query |
|||
* @param {LatLng} query.location |
|||
* @param {Date|number} [query.timestamp] |
|||
* @param {string} [query.language] |
|||
* @param {ResponseCallback} callback Callback function for handling the result |
|||
* @return {RequestHandle} |
|||
*/ |
|||
exports.timezone = { |
|||
url: 'https://maps.googleapis.com/maps/api/timezone/json', |
|||
validator: v.object({ |
|||
location: utils.latLng, |
|||
timestamp: utils.timeStamp, |
|||
language: v.optional(v.string), |
|||
retryOptions: v.optional(utils.retryOptions), |
|||
timeout: v.optional(v.number) |
|||
}) |
|||
}; |
@ -0,0 +1,106 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/ |
|||
|
|||
/** |
|||
* Google Maps Service module. |
|||
* @module @google/maps |
|||
*/ |
|||
|
|||
/** |
|||
* Creates a Google Maps client. The client object contains all the API methods. |
|||
* |
|||
* @param {Object} options |
|||
* @param {string} options.key API key (required, unless clientID and |
|||
* clientSecret provided). |
|||
* @param {string=} options.clientId Maps API for Work client ID. |
|||
* @param {string=} options.clientSecret Maps API for Work client secret (a.k.a. |
|||
* private key). |
|||
* @param {string=} options.channel Maps API for Work channel. |
|||
* @param {number=} options.timeout Timeout in milliseconds. |
|||
* (Default: 60 * 1000 ms) |
|||
* @param {string=} options.language Default language for all queries. |
|||
See https://developers.google.com/maps/faq#languagesupport
|
|||
* @param {number=} options.rate.limit Controls rate-limiting of requests. |
|||
* Maximum number of requests per period. (Default: 10) |
|||
* @param {number=} options.rate.period Period for rate limit, in milliseconds. |
|||
* (Default: 1000 ms) |
|||
* @param {number=} options.retryOptions.interval If a transient server error |
|||
* occurs, how long to wait before retrying the request, in milliseconds. |
|||
* (Default: 500 ms) |
|||
* @param {Function=} options.Promise - Promise constructor (optional). |
|||
* @return {GoogleMapsClient} The client object containing all API methods. |
|||
*/ |
|||
exports.createClient = function(options) { |
|||
|
|||
options = options || {}; |
|||
var makeApiCall = require('./internal/make-api-call').inject(options); |
|||
var deprecate = require('util').deprecate; |
|||
|
|||
var makeApiMethod = function(apiConfig) { |
|||
return function(query, callback, customParams) { |
|||
query = apiConfig.validator(query); |
|||
query.supportsClientId = apiConfig.supportsClientId !== false; |
|||
query.options = apiConfig.options; |
|||
if (options.language && !query.language) { |
|||
query.language = options.language; |
|||
} |
|||
// Merge query and customParams.
|
|||
var finalQuery = {}; |
|||
customParams = customParams || {}; |
|||
[customParams, query].map(function(obj) { |
|||
Object.keys(obj).sort().map(function(key) { |
|||
finalQuery[key] = obj[key]; |
|||
}); |
|||
}); |
|||
return makeApiCall(apiConfig.url, finalQuery, callback); |
|||
}; |
|||
}; |
|||
|
|||
var geocode = require('./apis/geocode'); |
|||
var geolocation = require('./apis/geolocation'); |
|||
var timezone = require('./apis/timezone'); |
|||
var directions = require('./apis/directions'); |
|||
var distanceMatrix = require('./apis/distance-matrix'); |
|||
var elevation = require('./apis/elevation'); |
|||
var roads = require('./apis/roads'); |
|||
var places = require('./apis/places'); |
|||
|
|||
return { |
|||
directions: makeApiMethod(directions.directions), |
|||
distanceMatrix: makeApiMethod(distanceMatrix.distanceMatrix), |
|||
elevation: makeApiMethod(elevation.elevation), |
|||
elevationAlongPath: makeApiMethod(elevation.elevationAlongPath), |
|||
geocode: makeApiMethod(geocode.geocode), |
|||
geolocate: makeApiMethod(geolocation.geolocate), |
|||
reverseGeocode: makeApiMethod(geocode.reverseGeocode), |
|||
places: makeApiMethod(places.places), |
|||
placesNearby: makeApiMethod(places.placesNearby), |
|||
placesRadar: deprecate(makeApiMethod(places.placesRadar), 'placesRadar is deprecated, see http://goo.gl/BGiumE'), |
|||
place: makeApiMethod(places.place), |
|||
placesPhoto: makeApiMethod(places.placesPhoto), |
|||
placesAutoComplete: makeApiMethod(places.placesAutoComplete), |
|||
placesQueryAutoComplete: makeApiMethod(places.placesQueryAutoComplete), |
|||
snapToRoads: makeApiMethod(roads.snapToRoads), |
|||
nearestRoads: makeApiMethod(roads.nearestRoads), |
|||
speedLimits: makeApiMethod(roads.speedLimits), |
|||
snappedSpeedLimits: makeApiMethod(roads.snappedSpeedLimits), |
|||
timezone: makeApiMethod(timezone.timezone) |
|||
}; |
|||
|
|||
}; |
|||
|
|||
exports.cli = require('./internal/cli'); |
@ -0,0 +1,54 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/ |
|||
|
|||
exports.inject = function(wait) { |
|||
var Task = require('./task'); |
|||
|
|||
return { |
|||
/** |
|||
* Repeatedly calls the 'do' function, until its result passes the 'until' |
|||
* predicate, or timeout. The 'do' function is retried with exponential |
|||
* backoff. |
|||
* |
|||
* @param {function(): Task<T>} options.do Starts the task to try |
|||
* repeatedly. |
|||
* @param {function(T): boolean} options.until A predicate that checks |
|||
* whether the result of options.do was successful. |
|||
* @return {Task<T>} |
|||
* @template T |
|||
*/ |
|||
attempt: function(options) { |
|||
var doSomething = options['do']; |
|||
var isSuccessful = options.until; |
|||
var interval = options.interval || 500; |
|||
var increment = options.increment || 1.5; |
|||
var jitter = options.jitter || 0.5; |
|||
|
|||
return Task.withValue().thenDo(function loop() { |
|||
return doSomething().thenDo(function(result) { |
|||
if (isSuccessful(result)) { |
|||
return Task.withValue(result); |
|||
} |
|||
|
|||
var delay = interval * (1 + jitter * (2 * Math.random() - 1)); |
|||
interval *= increment; |
|||
return wait(delay).thenDo(loop); |
|||
}); |
|||
}); |
|||
} |
|||
}; |
|||
}; |
@ -0,0 +1,40 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/ |
|||
|
|||
exports.create = function(size) { |
|||
var items = []; |
|||
var current = 0; |
|||
|
|||
return { |
|||
/** |
|||
* Inserts an item into the circular buffer. The new item will have index 0, |
|||
* and all other items will have their index incremented. |
|||
*/ |
|||
insert: function(item) { |
|||
current = (current + 1) % size; |
|||
items[current] = item; |
|||
}, |
|||
/** |
|||
* Returns the i-th item from the buffer. i=0 is the most-recently-inserted |
|||
* item. i=1 is the second-most-recently-inserted item. Returns undefined if |
|||
* i+1 items have not yet been inserted. |
|||
*/ |
|||
item: function(i) { |
|||
return items[(current - i + size) % size]; |
|||
} |
|||
}; |
|||
}; |
@ -0,0 +1,39 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/ |
|||
|
|||
|
|||
exports.parseArgs = function(argv) { |
|||
var parsed = {}; |
|||
var argv = argv || process.argv.slice(2); |
|||
for (var i = 0; i < argv.length; i += 2) { |
|||
var value = argv[i + 1]; |
|||
try { |
|||
value = JSON.parse(value); |
|||
} catch (e) { |
|||
} |
|||
parsed[argv[i].replace(/^-*/g, '')] = value; |
|||
} |
|||
return parsed; |
|||
}; |
|||
|
|||
exports.callback = function(error, response) { |
|||
if (error) { |
|||
console.log("Error:", error.message != undefined ? error.message : error); |
|||
} else { |
|||
console.log(JSON.stringify(response.json, null, 4)); |
|||
} |
|||
}; |
@ -0,0 +1,90 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/ |
|||
|
|||
var v = require('./validate'); |
|||
|
|||
var asArray = function(arg) { |
|||
return Array.isArray(arg) ? arg : [arg]; |
|||
}; |
|||
|
|||
exports.pipedKeyValues = function(arg) { |
|||
if (!arg || typeof arg !== 'object') { |
|||
throw new v.InvalidValueError('not an Object'); |
|||
} |
|||
return Object.keys(arg).sort().map(function(key) { |
|||
return key + ':' + arg[key]; |
|||
}).join('|'); |
|||
}; |
|||
|
|||
exports.locations = function(arg) { |
|||
if (Array.isArray(arg) && arg.length == 2 && typeof arg[0] == 'number' && typeof arg[1] == 'number') { |
|||
arg = [arg]; |
|||
} |
|||
return asArray(arg).map(exports.latLng).join('|'); |
|||
}; |
|||
|
|||
exports.pipedArrayOf = function(validateItem) { |
|||
var validateArray = v.array(validateItem); |
|||
return function(value) { |
|||
value = validateArray(asArray(value)); |
|||
return value.join('|'); |
|||
}; |
|||
}; |
|||
|
|||
exports.latLng = function(arg) { |
|||
if (!arg) { |
|||
throw new v.InvalidValueError(); |
|||
} else if (arg.lat != undefined && arg.lng != undefined) { |
|||
arg = [arg.lat, arg.lng]; |
|||
} else if (arg.latitude != undefined && arg.longitude != undefined) { |
|||
arg = [arg.latitude, arg.longitude]; |
|||
} |
|||
return asArray(arg).join(','); |
|||
}; |
|||
|
|||
var validateBounds = v.object({ |
|||
south: v.number, |
|||
west: v.number, |
|||
north: v.number, |
|||
east: v.number |
|||
}); |
|||
|
|||
exports.bounds = function(arg) { |
|||
arg = validateBounds(arg); |
|||
return arg.south + ',' + arg.west + '|' + arg.north + ',' + arg.east; |
|||
}; |
|||
|
|||
exports.timeStamp = function(arg) { |
|||
if (arg == undefined) { |
|||
arg = new Date(); |
|||
} |
|||
if (arg.getTime) { |
|||
arg = arg.getTime(); |
|||
// NOTE: Unix time is seconds past epoch.
|
|||
return Math.round(arg / 1000); |
|||
} |
|||
|
|||
// Otherwise assume arg is Unix time
|
|||
return arg; |
|||
}; |
|||
|
|||
exports.retryOptions = v.object({ |
|||
timeout: v.optional(v.number), |
|||
interval: v.optional(v.number), |
|||
increment: v.optional(v.number), |
|||
jitter: v.optional(v.number) |
|||
}); |
@ -0,0 +1,221 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/ |
|||
|
|||
var url = require('url'); |
|||
var Task = require('./task'); |
|||
|
|||
exports.inject = function(options) { |
|||
|
|||
var key = options.key || process.env.GOOGLE_MAPS_API_KEY; |
|||
var channel = options.channel; |
|||
var clientId = options.clientId || process.env.GOOGLE_MAPS_API_CLIENT_ID; |
|||
var clientSecret = options.clientSecret || process.env.GOOGLE_MAPS_API_CLIENT_SECRET; |
|||
|
|||
var rate = options.rate || {}; |
|||
var rateLimit = rate.limit || 10; // 10 requests per ratePeriod.
|
|||
var ratePeriod = rate.period || 1000; // 1 second.
|
|||
|
|||
var makeUrlRequest = options.makeUrlRequest || require('./make-url-request'); |
|||
var mySetTimeout = options.setTimeout || setTimeout; |
|||
var myClearTimeout = options.clearTimeout || clearTimeout; |
|||
var getTime = options.getTime || function() {return new Date().getTime();}; |
|||
var wait = require('./wait').inject(mySetTimeout, myClearTimeout); |
|||
var attempt = require('./attempt').inject(wait).attempt; |
|||
var ThrottledQueue = require('./throttled-queue').inject(wait, getTime); |
|||
var requestQueue = ThrottledQueue.create(rateLimit, ratePeriod); |
|||
|
|||
/** |
|||
* Makes an API request using the injected makeUrlRequest. |
|||
* |
|||
* Inserts the API key (or client ID and signature) into the query |
|||
* parameters. Retries requests when the status code requires it. |
|||
* Parses the response body as JSON. |
|||
* |
|||
* The callback is given either an error or a response. The response |
|||
* is an object with the following entries: |
|||
* { |
|||
* status: number, |
|||
* body: string, |
|||
* json: Object |
|||
* } |
|||
* |
|||
* @param {string} path |
|||
* @param {Object} query This function mutates the query object. |
|||
* @param {Function} callback |
|||
* @return {{ |
|||
* cancel: function(), |
|||
* finally: function(function()), |
|||
* asPromise: function(): Promise |
|||
* }} |
|||
*/ |
|||
return function(path, query, callback) { |
|||
|
|||
callback = callback || function() {}; |
|||
|
|||
var retryOptions = query.retryOptions || options.retryOptions || {}; |
|||
delete query.retryOptions; |
|||
|
|||
var timeout = query.timeout || options.timeout || 60 * 1000; |
|||
delete query.timeout; |
|||
|
|||
var useClientId = query.supportsClientId && clientId && clientSecret; |
|||
delete query.supportsClientId; |
|||
|
|||
var queryOptions = query.options || {}; |
|||
delete query.options; |
|||
|
|||
var isPost = queryOptions.method === 'POST' |
|||
var requestUrl = formatRequestUrl(path, isPost ? {} : query, useClientId); |
|||
|
|||
if (isPost) { |
|||
queryOptions.body = query; |
|||
} |
|||
|
|||
// Determines whether a response indicates a retriable error.
|
|||
var canRetry = queryOptions.canRetry || function(response) { |
|||
return ( |
|||
response == null |
|||
|| response.status === 500 |
|||
|| response.status === 503 |
|||
|| response.status === 504 |
|||
|| (response.json && ( |
|||
response.json.status === 'OVER_QUERY_LIMIT' || |
|||
response.json.status === 'RESOURCE_EXHAUSTED'))); |
|||
}; |
|||
delete queryOptions.canRetry; |
|||
|
|||
// Determines whether a response indicates success.
|
|||
var isSuccessful = queryOptions.isSuccessful || function(response) { |
|||
return response.status === 200 && ( |
|||
response.json == undefined || |
|||
response.json.status === undefined || |
|||
response.json.status === 'OK' || |
|||
response.json.status === 'ZERO_RESULTS'); |
|||
}; |
|||
delete queryOptions.isSuccessful; |
|||
|
|||
function rateLimitedGet() { |
|||
return requestQueue.add(function() { |
|||
return Task.start(function(resolve, reject) { |
|||
return makeUrlRequest(requestUrl, resolve, reject, queryOptions); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
var timeoutTask = wait(timeout).thenDo(function() { |
|||
throw 'timeout'; |
|||
}); |
|||
var requestTask = attempt({ |
|||
'do': rateLimitedGet, |
|||
until: function(response) { return !canRetry(response); }, |
|||
interval: retryOptions.interval, |
|||
increment: retryOptions.increment, |
|||
jitter: retryOptions.jitter |
|||
}); |
|||
|
|||
var task = |
|||
Task.race([timeoutTask, requestTask]) |
|||
.thenDo(function(response) { |
|||
// We add the request url and the original query to the response
|
|||
// to be able to use them when debugging errors.
|
|||
response.requestUrl = requestUrl; |
|||
response.query = query; |
|||
|
|||
if (isSuccessful(response)) { |
|||
return Task.withValue(response); |
|||
} else { |
|||
return Task.withError(response); |
|||
} |
|||
}) |
|||
.thenDo( |
|||
function(response) { callback(null, response); }, |
|||
function(err) { callback(err); }); |
|||
|
|||
if (options.Promise) { |
|||
var originalCallback = callback; |
|||
var promise = new options.Promise(function(resolve, reject) { |
|||
callback = function(err, result) { |
|||
if (err != null) { |
|||
reject(err); |
|||
} else { |
|||
resolve(result); |
|||
} |
|||
originalCallback(err, result); |
|||
}; |
|||
}); |
|||
task.asPromise = function() { return promise; }; |
|||
} |
|||
|
|||
delete task.thenDo; |
|||
return task; |
|||
}; |
|||
|
|||
/** |
|||
* Adds auth information to the query, and formats it into a URL. |
|||
* @param {string} path |
|||
* @param {Object} query |
|||
* @param {boolean} useClientId |
|||
* @return {string} The formatted URL. |
|||
*/ |
|||
function formatRequestUrl(path, query, useClientId) { |
|||
if (channel) { |
|||
query.channel = channel; |
|||
} |
|||
if (useClientId) { |
|||
query.client = clientId; |
|||
} else if (key && key.indexOf('AIza') == 0) { |
|||
query.key = key; |
|||
} else { |
|||
throw 'Missing either a valid API key, or a client ID and secret'; |
|||
} |
|||
|
|||
var requestUrl = url.format({pathname: path, query: query}); |
|||
|
|||
// When using client ID, generate and append the signature param.
|
|||
if (useClientId) { |
|||
var secret = new Buffer(clientSecret, 'base64'); |
|||
var payload = url.parse(requestUrl).path; |
|||
var signature = computeSignature(secret, payload); |
|||
requestUrl += '&signature=' + encodeURIComponent(signature); |
|||
} |
|||
|
|||
return requestUrl; |
|||
} |
|||
|
|||
/** |
|||
* @param {string} secret |
|||
* @param {string} payload |
|||
* @return {string} |
|||
*/ |
|||
function computeSignature(secret, payload) { |
|||
var signature = |
|||
new Buffer( |
|||
require('crypto') |
|||
.createHmac('sha1', secret) |
|||
.update(payload) |
|||
.digest('base64')) |
|||
.toString() |
|||
.replace(/\+/g, '-') |
|||
.replace(/\//g, '_') |
|||
.replace(/=+$/, ''); |
|||
while (signature.length % 4) { |
|||
signature += '='; |
|||
} |
|||
return signature; |
|||
} |
|||
|
|||
}; |
@ -0,0 +1,109 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/ |
|||
|
|||
var https = require('https'); |
|||
var parse = require('url').parse; |
|||
var version = require('../version'); |
|||
|
|||
|
|||
// add keep-alive header to speed up request
|
|||
var agent = new https.Agent({ keepAlive: true }); |
|||
|
|||
|
|||
/** |
|||
* Makes a secure HTTP GET request for the given URL. |
|||
* |
|||
* Calls the callback with two parameters (err, response). If there was an |
|||
* error, response should be null. If there was no error, err should be null, |
|||
* and response should be an object with these properties |
|||
* { |
|||
* status: number, |
|||
* headers: Object, |
|||
* json: Object |
|||
* } |
|||
* |
|||
* Returns a function that cancels the request. |
|||
* |
|||
* @param {string} url |
|||
* @param {function(ClientResponse)} onSuccess |
|||
* @param {function(?)} onError |
|||
* @param {Object} options |
|||
* @return {function()} |
|||
*/ |
|||
module.exports = function makeUrlRequest(url, onSuccess, onError, options) { |
|||
|
|||
var requestOptions = parse(url); |
|||
var body; |
|||
|
|||
// Allow each API to provide some of the request options such as the
|
|||
// HTTP method, headers, etc.
|
|||
if (options) { |
|||
for (var k in options) { |
|||
if (k === 'body') { |
|||
body = options[k]; |
|||
} else { |
|||
requestOptions[k] = options[k]; |
|||
} |
|||
} |
|||
} |
|||
|
|||
requestOptions.headers = requestOptions.headers || {}; |
|||
requestOptions.headers['User-Agent'] = 'GoogleGeoApiClientJS/' + version; |
|||
|
|||
var request = https.request(requestOptions, function(response) { |
|||
|
|||
response.on('error', function(error) { |
|||
onError(error); |
|||
}); |
|||
|
|||
if (response.statusCode === 302) { |
|||
// Handle redirect.
|
|||
var url = response.headers['location']; |
|||
makeUrlRequest(url, onSuccess, onError, options); |
|||
} else if (response.headers['content-type'] == 'application/json; charset=UTF-8') { |
|||
// Handle JSON.
|
|||
var data = []; |
|||
response.on('data', function(chunk) { |
|||
data.push(chunk); |
|||
}); |
|||
response.on('end', function() { |
|||
onSuccess({ |
|||
status: response.statusCode, |
|||
headers: response.headers, |
|||
json: JSON.parse(Buffer.concat(data).toString()) |
|||
}) |
|||
}); |
|||
} else { |
|||
// Fallback is for binary data, namely places photo download,
|
|||
// so just provide the response stream. Also provide the same
|
|||
// consistent name for status checking as per JSON responses.
|
|||
response.status = response.statusCode; |
|||
onSuccess(response); |
|||
} |
|||
|
|||
}).on('error', function(error) { |
|||
onError(error); |
|||
}); |
|||
|
|||
if (body) { |
|||
request.write(JSON.stringify(body)); |
|||
} |
|||
|
|||
request.end(); |
|||
|
|||
return function cancel() { request.abort(); }; |
|||
}; |
@ -0,0 +1,269 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/ |
|||
|
|||
// This is a utility class that makes it easier to work with asynchronous tasks.
|
|||
// Here's why I don't just use Promises:
|
|||
// (a) I don't want to depend on a Promise implementation.
|
|||
// (b) Promises aren't cancellable (yet?), and I want cancellability.
|
|||
//
|
|||
// This is very stripped down, compared to Promises.
|
|||
// (a) You can only call .thenDo() once. Because there's only one party waiting
|
|||
// on the result of a task, cancelling always propagates backwards.
|
|||
// (b) The argument to .thenDo() must return either undefined or a Task. I don't
|
|||
// promote values to Tasks, like what happens with Promises.
|
|||
|
|||
var Task = exports; |
|||
|
|||
/** |
|||
* Creates a Task. |
|||
* |
|||
* The `doSomething` function is called immediately, so that it can start |
|||
* whatever work is part of this task. |
|||
* |
|||
* The `doSomething` function is given a resolve function and a reject function, |
|||
* and it should call one of them when the task is finished, to report its |
|||
* result. |
|||
* |
|||
* The `doSomething` function can optionally return a cancel function. This will |
|||
* be called if the task is cancelled. |
|||
* |
|||
* @param {function(function(T), function(?)): function()} doSomething |
|||
* @return {Task<T>} |
|||
* @template T |
|||
*/ |
|||
Task.start = function(doSomething) { |
|||
var me = {}; |
|||
|
|||
// onFinish should be called as soon as both finished and onFinish are
|
|||
// defined. It should be called by the piece of code that just defined either
|
|||
// finished or onFinish.
|
|||
var finished; |
|||
var onFinish; |
|||
var cleaners = []; |
|||
|
|||
function finish(err, result) { |
|||
if (!finished) { |
|||
finished = {err: err, result: result}; |
|||
|
|||
if (onFinish) { |
|||
onFinish(); |
|||
// To prevent memory leaks, delete our reference to onFinish after
|
|||
// calling it.
|
|||
onFinish = function() {}; |
|||
} |
|||
|
|||
var cleanup; |
|||
while (cleanup = cleaners.pop()) { |
|||
cleanup(); |
|||
} |
|||
|
|||
if (err === 'cancelled') { |
|||
if (abort) abort(); |
|||
} |
|||
|
|||
abort = null; |
|||
} |
|||
} |
|||
|
|||
try { |
|||
// doSomething must be called immediately.
|
|||
var abort = doSomething( |
|||
function(result) { finish(null, result); }, |
|||
function(err) { finish(err, null); }); |
|||
} catch (err) { |
|||
finish(err, null); |
|||
} |
|||
|
|||
/** |
|||
* Cancels the task (unless the task has already finished, in which case |
|||
* this call is ignored). |
|||
* |
|||
* Subsequent tasks created with #thenDo will not be started. However, clean- |
|||
* up code added with #finished will run. |
|||
*/ |
|||
me.cancel = function() { |
|||
finish('cancelled', null); |
|||
}; |
|||
|
|||
/** |
|||
* Sets the listener that will be called with the result of this task, when |
|||
* finished. This function can be called at most once. |
|||
* |
|||
* @param {function(?, T)} callback |
|||
*/ |
|||
function setListener(callback) { |
|||
if (onFinish) { |
|||
throw new Error('thenDo/finally called more than once'); |
|||
} |
|||
if (finished) { |
|||
onFinish = function() {}; |
|||
callback(finished.err, finished.result); |
|||
} else { |
|||
onFinish = function() { |
|||
callback(finished.err, finished.result); |
|||
}; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Creates and returns a composite task, consisting of this task and a |
|||
* subsequent task. |
|||
* |
|||
* @param {function(T): ?Task<U>} onResolve A function that will |
|||
* create a subsequent task. This function will be called |
|||
* asynchronously, with the result of this task, when it |
|||
* finishes. The return value must be a Task, or null/undefined. |
|||
* @param {function(?): ?Task<U>} onReject A function that will |
|||
* create a subsequent task. This function will be called |
|||
* asynchronously, with the error produced by this task, when it |
|||
* finishes. The return value must be a Task, or null/undefined. |
|||
* @return {Task<U>} The composite task. Cancelling the composite task cancels |
|||
* either this task or the subsequent task, depending on whether this |
|||
* task is finished. |
|||
* @template U |
|||
*/ |
|||
me.thenDo = function(onResolve, onReject) { |
|||
return compose(me, setListener, onResolve, onReject); |
|||
}; |
|||
|
|||
/** |
|||
* Registers a cleanup function, that will be run when the task finishes, |
|||
* regardless of error or cancellation. |
|||
* |
|||
* @param {function()} cleanup |
|||
* @return {THIS} |
|||
*/ |
|||
me.finally = function(cleanup) { |
|||
if (!finished) { |
|||
cleaners.push(function() { |
|||
process.nextTick(cleanup); |
|||
}); |
|||
} else { |
|||
process.nextTick(cleanup); |
|||
} |
|||
return me; |
|||
}; |
|||
|
|||
return me; |
|||
}; |
|||
|
|||
/** |
|||
* Creates a Task with the given result. |
|||
*/ |
|||
Task.withValue = function(result) { |
|||
return Task.start(function(resolve) { |
|||
resolve(result); |
|||
}); |
|||
}; |
|||
|
|||
/** |
|||
* Creates a Task with the given error. |
|||
*/ |
|||
Task.withError = function(err) { |
|||
return Task.start(function(resolve, reject) { |
|||
reject(err); |
|||
}); |
|||
}; |
|||
|
|||
/** |
|||
* Returns a new task that races the given tasks. Eventually finishes with the |
|||
* result or error of whichever task finishes first. If any task is cancelled, |
|||
* all of the tasks are cancelled. |
|||
* |
|||
* @param {Array<Task<T>>} tasks |
|||
* @return {Task<T>} |
|||
* @template T |
|||
*/ |
|||
Task.race = function(tasks) { |
|||
return Task.start(function(resolve, reject) { |
|||
function cancelAll() { |
|||
tasks.forEach(function(task) { |
|||
task.cancel(); |
|||
}); |
|||
} |
|||
tasks.forEach(function(task) { |
|||
task.finally(cancelAll).thenDo(resolve, reject); |
|||
}); |
|||
return cancelAll; |
|||
}); |
|||
}; |
|||
|
|||
/** |
|||
* Creates a composite task, which uses the output of the first task to create |
|||
* a subsequent task, and represents the two tasks together. |
|||
* |
|||
* This function is internal-only. It is used by Task.thenDo(). |
|||
* |
|||
* @param {Task<T>} firstTask |
|||
* @param {function(function(?, T))} whenFirstTaskFinishes The private |
|||
* setListener method on the firstTask. |
|||
* @param {function(T): Task<U>} onResolve |
|||
* @param {function(?): Task<U>} onReject |
|||
* @return {Task<U>} |
|||
* @template T, U |
|||
*/ |
|||
function compose(firstTask, whenFirstTaskFinishes, onResolve, onReject) { |
|||
return Task.start(function(resolve, reject) { |
|||
var cancelled; |
|||
var currentTask = firstTask; |
|||
|
|||
whenFirstTaskFinishes(function(err, result) { |
|||
currentTask = null; |
|||
// createSubsequentTask must be called asynchronously.
|
|||
process.nextTick(function() { |
|||
if (cancelled || err === 'cancelled') { |
|||
return reject('cancelled'); |
|||
} |
|||
|
|||
// Start the subsequent task.
|
|||
if (err == null) { |
|||
if (!onResolve) { |
|||
return resolve(result); |
|||
} |
|||
try { |
|||
currentTask = onResolve(result); |
|||
} catch (caughtErr) { |
|||
return reject(caughtErr); |
|||
} |
|||
} else { |
|||
if (!onReject) { |
|||
return reject(err); |
|||
} |
|||
try { |
|||
currentTask = onReject(err); |
|||
} catch (caughtErr) { |
|||
return reject(caughtErr); |
|||
} |
|||
} |
|||
|
|||
// Was a subsequent task returned?
|
|||
if (!currentTask) { |
|||
return resolve(undefined); |
|||
} |
|||
|
|||
currentTask.thenDo(resolve, reject); |
|||
}); |
|||
}); |
|||
|
|||
return function cancelCompositeTask() { |
|||
cancelled = true; |
|||
if (currentTask) { |
|||
currentTask.cancel(); |
|||
} |
|||
}; |
|||
}); |
|||
} |
@ -0,0 +1,74 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/ |
|||
|
|||
var CircularBuffer = require('./circular-buffer'); |
|||
var Task = require('./task'); |
|||
|
|||
exports.inject = function(wait, getTime) { |
|||
return { |
|||
/** |
|||
* Creates a ThrottledQueue. The queue stores tasks, which will be executed |
|||
* asynchronously, at a controlled rate. |
|||
* |
|||
* @param {number} limit The maximum number of tasks that can be executed |
|||
* over one period. |
|||
* @param {number} period The time period (ms) over which limit is |
|||
* enforceable. |
|||
* @return {ThrottledQueue} |
|||
*/ |
|||
create: function(limit, period) { |
|||
var me = {}; |
|||
var queue = Task.withValue(); |
|||
var recentTimes = CircularBuffer.create(limit); |
|||
|
|||
/** |
|||
* Adds a task to the work queue. |
|||
* |
|||
* @param {function(): Task<T>} doSomething Starts the task. This function |
|||
* will be called when the rate limit allows. |
|||
* @return {Task<T>} The delayed task. |
|||
* @template T |
|||
*/ |
|||
me.add = function(doSomething) { |
|||
// Return a separate task from the queue, so that cancelling a task
|
|||
// doesn't propagate back and cancel the whole queue.
|
|||
var waitForMyTurn = Task |
|||
.start(function(resolve) { |
|||
queue.finally(resolve); |
|||
}) |
|||
.thenDo(function() { |
|||
var lastTime = recentTimes.item(limit - 1); |
|||
if (lastTime == undefined) return; |
|||
return wait(Math.max(lastTime + period - getTime(), 0)); |
|||
}) |
|||
.thenDo(function() { |
|||
recentTimes.insert(getTime()); |
|||
}); |
|||
|
|||
queue = queue.thenDo(function() { |
|||
return Task.start(function(resolve) { |
|||
waitForMyTurn.finally(resolve); |
|||
}); |
|||
}); |
|||
|
|||
return waitForMyTurn.thenDo(doSomething); |
|||
}; |
|||
|
|||
return me; |
|||
} |
|||
}; |
|||
}; |
@ -0,0 +1,175 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/ |
|||
|
|||
var Validate = exports; |
|||
|
|||
function InvalidValueError(message) { |
|||
this.message = message; |
|||
this.name = 'InvalidValueError'; |
|||
Error.captureStackTrace(this, InvalidValueError); |
|||
} |
|||
InvalidValueError.prototype = Object.create(Error.prototype); |
|||
InvalidValueError.prototype.constructor = InvalidValueError; |
|||
|
|||
InvalidValueError.prepend = function(message, error) { |
|||
if (error instanceof InvalidValueError) { |
|||
return new InvalidValueError(message + ': ' + error.message); |
|||
} |
|||
return error; |
|||
}; |
|||
|
|||
Validate.InvalidValueError = InvalidValueError; |
|||
|
|||
Validate.acceptAll = function(value) { |
|||
return value; |
|||
}; |
|||
|
|||
Validate.optional = function(validator) { |
|||
return function(value) { |
|||
return (value == undefined) ? value : validator(value); |
|||
}; |
|||
}; |
|||
|
|||
Validate.that = function(predicate, message) { |
|||
return function(value) { |
|||
if (predicate(value)) return value; |
|||
throw new InvalidValueError(message); |
|||
}; |
|||
}; |
|||
|
|||
Validate.number = Validate.that(function(value) { |
|||
return typeof value === 'number'; |
|||
}, 'not a number'); |
|||
|
|||
Validate.string = Validate.that(function(value) { |
|||
return typeof value === 'string'; |
|||
}, 'not a string'); |
|||
|
|||
Validate.object = function(propertyValidators) { |
|||
return function(object) { |
|||
var result = {}; |
|||
|
|||
if (!object || typeof object !== 'object') { |
|||
throw new InvalidValueError('not an Object'); |
|||
} |
|||
|
|||
// Validate all properties.
|
|||
for (key in propertyValidators) { |
|||
var validator = propertyValidators[key]; |
|||
try { |
|||
var valid = validator(object[key]); |
|||
} catch (error) { |
|||
if (key in object) { |
|||
throw InvalidValueError.prepend('in property "' + key + '"', error); |
|||
} else { |
|||
throw new InvalidValueError('missing property "' + key + '"'); |
|||
} |
|||
} |
|||
if (valid !== undefined) { |
|||
result[key] = valid; |
|||
} |
|||
} |
|||
|
|||
// Check for unexpected properties.
|
|||
for (var key in object) { |
|||
if (!propertyValidators[key]) { |
|||
throw new InvalidValueError('unexpected property "' + key + '"'); |
|||
} |
|||
} |
|||
|
|||
return result; |
|||
}; |
|||
}; |
|||
|
|||
Validate.array = function(validator) { |
|||
return function(array) { |
|||
var result = []; |
|||
|
|||
if (Object.prototype.toString.call(array) !== '[object Array]') { |
|||
throw new InvalidValueError('not an Array'); |
|||
} |
|||
|
|||
for (var i = 0; i < array.length; ++i) { |
|||
try { |
|||
result[i] = validator(array[i]); |
|||
} catch (error) { |
|||
throw InvalidValueError.prepend('at index ' + i, error); |
|||
} |
|||
} |
|||
|
|||
return result; |
|||
}; |
|||
}; |
|||
|
|||
Validate.oneOf = function(names) { |
|||
var myObject = {}; |
|||
var quotedNames = []; |
|||
names.forEach(function(name) { |
|||
myObject[name] = true; |
|||
quotedNames.push('"' + name + '"'); |
|||
}); |
|||
|
|||
return function(value) { |
|||
if (myObject[value]) return value; |
|||
throw new InvalidValueError('not one of ' + quotedNames.join(', ')); |
|||
}; |
|||
}; |
|||
|
|||
Validate.mutuallyExclusiveProperties = function(names) { |
|||
return function(value) { |
|||
if (!value) return value; |
|||
|
|||
var present = []; |
|||
names.forEach(function(name) { |
|||
if (name in value) { |
|||
present.push('"' + name + '"'); |
|||
} |
|||
}); |
|||
|
|||
if (present.length > 1) { |
|||
throw new InvalidValueError( |
|||
'cannot specify properties ' |
|||
+ present.slice(0, -1).join(', ') |
|||
+ ' and ' |
|||
+ present.slice(-1) |
|||
+ ' together'); |
|||
} |
|||
|
|||
return value; |
|||
}; |
|||
}; |
|||
|
|||
Validate.compose = function(validators) { |
|||
return function(value) { |
|||
validators.forEach(function(validate) { |
|||
value = validate(value); |
|||
}); |
|||
return value; |
|||
}; |
|||
}; |
|||
|
|||
Validate.boolean = Validate.compose([ |
|||
Validate.that(function(value) { |
|||
return typeof value === 'boolean'; |
|||
}, 'not a boolean'), |
|||
function(value) { |
|||
// In each API, boolean fields default to false, and the presence of
|
|||
// a querystring value indicates true, so we omit the value if
|
|||
// explicitly set to false.
|
|||
return value ? value : undefined; |
|||
} |
|||
]); |
@ -0,0 +1,34 @@ |
|||
/** |
|||
* @license |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/ |
|||
|
|||
var Task = require('./task'); |
|||
|
|||
exports.inject = function(setTimeout, clearTimeout) { |
|||
/** |
|||
* Returns a task that waits for the given delay. |
|||
* @param {number} delayMs |
|||
* @return {Task<undefined>} |
|||
*/ |
|||
return function wait(delayMs) { |
|||
return Task.start(function(resolve) { |
|||
var id = setTimeout(resolve, delayMs); |
|||
return function cancel() { |
|||
clearTimeout(id); |
|||
}; |
|||
}); |
|||
} |
|||
}; |
@ -0,0 +1 @@ |
|||
module.exports = '0.0.1'; |
@ -0,0 +1,85 @@ |
|||
{ |
|||
"_from": "@google/maps", |
|||
"_id": "@google/maps@0.4.5", |
|||
"_inBundle": false, |
|||
"_integrity": "sha1-cuuc+OfelEYZJF0Pjz+WlXHqhNg=", |
|||
"_location": "/@google/maps", |
|||
"_phantomChildren": {}, |
|||
"_requested": { |
|||
"type": "tag", |
|||
"registry": true, |
|||
"raw": "@google/maps", |
|||
"name": "@google/maps", |
|||
"escapedName": "@google%2fmaps", |
|||
"scope": "@google", |
|||
"rawSpec": "", |
|||
"saveSpec": null, |
|||
"fetchSpec": "latest" |
|||
}, |
|||
"_requiredBy": [ |
|||
"#USER", |
|||
"/" |
|||
], |
|||
"_resolved": "https://registry.npmjs.org/@google/maps/-/maps-0.4.5.tgz", |
|||
"_shasum": "72eb9cf8e7de944619245d0f8f3f969571ea84d8", |
|||
"_spec": "@google/maps", |
|||
"_where": "/var/www/htdocs/ordine", |
|||
"author": { |
|||
"name": "Google Inc." |
|||
}, |
|||
"bin": { |
|||
"googlemaps": "bin/run.js" |
|||
}, |
|||
"bugs": { |
|||
"url": "https://github.com/googlemaps/google-maps-services-js/issues" |
|||
}, |
|||
"bundleDependencies": false, |
|||
"contributors": [ |
|||
{ |
|||
"name": "Stephen Farrar", |
|||
"email": "step@google.com" |
|||
}, |
|||
{ |
|||
"name": "Stephen McDonald", |
|||
"email": "stephenmcd@google.com" |
|||
} |
|||
], |
|||
"deprecated": false, |
|||
"description": "Node.js client library for Google Maps API Web Services", |
|||
"devDependencies": { |
|||
"jasmine": ">=2.3.2 <2.5.0", |
|||
"jsdoc": "^3.4.0", |
|||
"priorityqueuejs": "^1.0.0", |
|||
"q": "^1.4.1" |
|||
}, |
|||
"files": [ |
|||
"lib", |
|||
"bin" |
|||
], |
|||
"homepage": "https://github.com/googlemaps/google-maps-services-js", |
|||
"keywords": [ |
|||
"google", |
|||
"maps", |
|||
"googlemaps", |
|||
"geo", |
|||
"geocode", |
|||
"timezone", |
|||
"api", |
|||
"client", |
|||
"roads", |
|||
"directions", |
|||
"navigation" |
|||
], |
|||
"license": "Apache-2.0", |
|||
"main": "./lib", |
|||
"name": "@google/maps", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/googlemaps/google-maps-services-js.git" |
|||
}, |
|||
"scripts": { |
|||
"jsdoc": "jsdoc -c docs/conf.json", |
|||
"test": "jasmine && jasmine spec/e2e/*.js" |
|||
}, |
|||
"version": "0.4.5" |
|||
} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,91 @@ |
|||
.banner, |
|||
.spot{ |
|||
|
|||
height: 150px; |
|||
border-radius: 3px;//0px 0px 3px 3px ; |
|||
position: relative; |
|||
padding: 5px; |
|||
|
|||
.content{ |
|||
background: $light-grey; |
|||
position: relative; |
|||
height: 100%; |
|||
overflow: hidden; |
|||
border-radius: 3px;//0px 0px 3px 3px ; |
|||
|
|||
.title{ |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
font-size: $font-10; |
|||
text-align: left; |
|||
padding: 4px; |
|||
background: rgba(0,0,0,0.5); |
|||
color: white; |
|||
width: 100%; |
|||
z-index: 1; |
|||
text-transform: uppercase; |
|||
} |
|||
|
|||
img{ |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
width: 100%; |
|||
height: 100%; |
|||
object-fit: cover; |
|||
object-position: center; |
|||
transition: .4s; |
|||
} |
|||
} |
|||
|
|||
&:hover{ |
|||
.content{ |
|||
img{ |
|||
transform: scale(1.2); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
.banner{ |
|||
height: 90px; |
|||
margin-bottom: 4px; |
|||
padding: 0; |
|||
} |
|||
|
|||
.contacts{ |
|||
padding: 15px 25px; |
|||
font-size: $font-12; |
|||
.fa{ |
|||
color: $green; |
|||
width: 25px; |
|||
font-size: $font-16; |
|||
height: 25px; |
|||
} |
|||
b{ |
|||
color: $green; |
|||
} |
|||
} |
|||
|
|||
.last-news{ |
|||
font-size: $font-12; |
|||
.item{ |
|||
border-bottom: 1px solid $light-grey; |
|||
padding: 8px 10px; |
|||
.date{ |
|||
color: $red; |
|||
} |
|||
a{ |
|||
color: $dark-grey; |
|||
text-decoration: none; |
|||
transition: .4s; |
|||
&:hover{ |
|||
color: black; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
Loading…
Reference in new issue