Firebase Update

This commit is contained in:
Lukas Nowy
2018-12-22 23:30:39 +01:00
parent befb44764d
commit acffe619b3
11523 changed files with 1614327 additions and 930246 deletions

View File

@ -0,0 +1,19 @@
# The names of individuals who have contributed to this project.
#
# Names are formatted as:
# name <email>
#
Ali Ijaz Sheikh <ofrobots@google.com>
Austin Peterson <austin@akpwebdesign.com>
Dave Gramlich <callmehiphop@gmail.com>
Eric Uldall <ericuldall@gmail.com>
Ernest Landrito <landrito@google.com>
Jason Dobry <jdobry@google.com>
Justin King <jcking@mtu.edu>
Karolis Narkevicius <karolis.n@gmail.com>
Kelvin Jin <kelvinjin@google.com>
Luke Sneeringer <lukesneeringer@google.com>
Matthew Loring <matthewloring@users.noreply.github.com>
Michael Prentice <splaktar@gmail.com>
Stephen Sawchuk <sawchuk@gmail.com>
Tim Swast <swast@google.com>

View File

@ -0,0 +1,202 @@
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.

View File

@ -0,0 +1,79 @@
<img src="https://avatars2.githubusercontent.com/u/2810941?v=3&s=96" alt="Google Cloud Platform logo" title="Google Cloud Platform" align="right" height="96" width="96"/>
# [Google Cloud Common Module: Node.js Client](https://github.com/googlecloudplatform/google-cloud-node)
[![release level](https://img.shields.io/badge/release%20level-alpha-orange.svg?style&#x3D;flat)](https://cloud.google.com/terms/launch-stages)
[![CircleCI](https://img.shields.io/circleci/project/github/googleapis/nodejs-common.svg?style=flat)](https://circleci.com/gh/googleapis/nodejs-common)
[![AppVeyor](https://ci.appveyor.com/api/projects/status/github/googleapis/nodejs-common?branch=master&svg=true)](https://ci.appveyor.com/project/googleapis/nodejs-common)
[![codecov](https://img.shields.io/codecov/c/github/googleapis/nodejs-common/master.svg?style=flat)](https://codecov.io/gh/googleapis/nodejs-common)
> Node.js Common package
Google Cloud Common node.js module contains stuff used by other Cloud API modules.
* [github.com/googlecloudplatform/google-cloud-node](https://github.com/googlecloudplatform/google-cloud-node)
Read more about the client libraries for Cloud APIs, including the older
Google APIs Client Libraries, in [Client Libraries Explained][explained].
[explained]: https://cloud.google.com/apis/docs/client-libraries-explained
**Table of contents:**
* [Quickstart](#quickstart)
* [Before you begin](#before-you-begin)
* [Installing the client library](#installing-the-client-library)
* [Using the client library](#using-the-client-library)
* [Versioning](#versioning)
* [Contributing](#contributing)
* [License](#license)
## Quickstart
### Before you begin
1. Select or create a Cloud Platform project.
[Go to the projects page][projects]
1. Enable billing for your project.
[Enable billing][billing]
1. [Set up authentication with a service account][auth] so you can access the
API from your local workstation.
[projects]: https://console.cloud.google.com/project
[billing]: https://support.google.com/cloud/answer/6293499#enable-billing
[auth]: https://cloud.google.com/docs/authentication/getting-started
### Installing the package
npm install --save @google-cloud/common
It's unlikely you will need to install this package directly, as it will be
installed as a dependency when you install other `@google-cloud` packages.
## Versioning
This library follows [Semantic Versioning](http://semver.org/).
This library is considered to be in **alpha**. This means it is still a
work-in-progress and under active development. Any release is subject to
backwards-incompatible changes at any time.
More Information: [Google Cloud Platform Launch Stages][launch_stages]
[launch_stages]: https://cloud.google.com/terms/launch-stages
## Contributing
Contributions welcome! See the [Contributing Guide](https://github.com/googlecloudplatform/google-cloud-node/blob/master/.github/CONTRIBUTING.md).
## License
Apache Version 2.0
See [LICENSE](https://github.com/googlecloudplatform/google-cloud-node/blob/master/LICENSE)
[shell_img]: http://gstatic.com/cloudssh/images/open-btn.png

View File

@ -0,0 +1 @@
node_modules

View File

@ -0,0 +1,4 @@
language: node_js
node_js:
- "0.8"
- "0.10"

View File

@ -0,0 +1,6 @@
test:
@node_modules/.bin/tape test.js
.PHONY: test

View File

@ -0,0 +1,60 @@
# isarray
`Array#isArray` for older browsers.
[![build status](https://secure.travis-ci.org/juliangruber/isarray.svg)](http://travis-ci.org/juliangruber/isarray)
[![downloads](https://img.shields.io/npm/dm/isarray.svg)](https://www.npmjs.org/package/isarray)
[![browser support](https://ci.testling.com/juliangruber/isarray.png)
](https://ci.testling.com/juliangruber/isarray)
## Usage
```js
var isArray = require('isarray');
console.log(isArray([])); // => true
console.log(isArray({})); // => false
```
## Installation
With [npm](http://npmjs.org) do
```bash
$ npm install isarray
```
Then bundle for the browser with
[browserify](https://github.com/substack/browserify).
With [component](http://component.io) do
```bash
$ component install juliangruber/isarray
```
## License
(MIT)
Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,19 @@
{
"name" : "isarray",
"description" : "Array#isArray for older browsers",
"version" : "0.0.1",
"repository" : "juliangruber/isarray",
"homepage": "https://github.com/juliangruber/isarray",
"main" : "index.js",
"scripts" : [
"index.js"
],
"dependencies" : {},
"keywords": ["browser","isarray","array"],
"author": {
"name": "Julian Gruber",
"email": "mail@juliangruber.com",
"url": "http://juliangruber.com"
},
"license": "MIT"
}

View File

@ -0,0 +1,5 @@
var toString = {}.toString;
module.exports = Array.isArray || function (arr) {
return toString.call(arr) == '[object Array]';
};

View File

@ -0,0 +1,73 @@
{
"_from": "isarray@~1.0.0",
"_id": "isarray@1.0.0",
"_inBundle": false,
"_integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"_location": "/@google-cloud/common/isarray",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "isarray@~1.0.0",
"name": "isarray",
"escapedName": "isarray",
"rawSpec": "~1.0.0",
"saveSpec": null,
"fetchSpec": "~1.0.0"
},
"_requiredBy": [
"/@google-cloud/common/readable-stream"
],
"_resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"_shasum": "bb935d48582cba168c06834957a54a3e07124f11",
"_spec": "isarray@~1.0.0",
"_where": "D:\\Desktop\\Git\\Firebase\\SmartShopperFirebase\\node_modules\\@google-cloud\\common\\node_modules\\readable-stream",
"author": {
"name": "Julian Gruber",
"email": "mail@juliangruber.com",
"url": "http://juliangruber.com"
},
"bugs": {
"url": "https://github.com/juliangruber/isarray/issues"
},
"bundleDependencies": false,
"dependencies": {},
"deprecated": false,
"description": "Array#isArray for older browsers",
"devDependencies": {
"tape": "~2.13.4"
},
"homepage": "https://github.com/juliangruber/isarray",
"keywords": [
"browser",
"isarray",
"array"
],
"license": "MIT",
"main": "index.js",
"name": "isarray",
"repository": {
"type": "git",
"url": "git://github.com/juliangruber/isarray.git"
},
"scripts": {
"test": "tape test.js"
},
"testling": {
"files": "test.js",
"browsers": [
"ie/8..latest",
"firefox/17..latest",
"firefox/nightly",
"chrome/22..latest",
"chrome/canary",
"opera/12..latest",
"opera/next",
"safari/5.1..latest",
"ipad/6.0..latest",
"iphone/6.0..latest",
"android-browser/4.2..latest"
]
},
"version": "1.0.0"
}

View File

@ -0,0 +1,20 @@
var isArray = require('./');
var test = require('tape');
test('is array', function(t){
t.ok(isArray([]));
t.notOk(isArray({}));
t.notOk(isArray(null));
t.notOk(isArray(false));
var obj = {};
obj[0] = true;
t.notOk(isArray(obj));
var arr = [];
arr.foo = 'bar';
t.ok(isArray(arr));
t.end();
});

View File

@ -0,0 +1,55 @@
sudo: false
language: node_js
before_install:
- npm install -g npm@2
- test $NPM_LEGACY && npm install -g npm@latest-3 || npm install npm -g
notifications:
email: false
matrix:
fast_finish: true
include:
- node_js: '0.8'
env:
- TASK=test
- NPM_LEGACY=true
- node_js: '0.10'
env:
- TASK=test
- NPM_LEGACY=true
- node_js: '0.11'
env:
- TASK=test
- NPM_LEGACY=true
- node_js: '0.12'
env:
- TASK=test
- NPM_LEGACY=true
- node_js: 1
env:
- TASK=test
- NPM_LEGACY=true
- node_js: 2
env:
- TASK=test
- NPM_LEGACY=true
- node_js: 3
env:
- TASK=test
- NPM_LEGACY=true
- node_js: 4
env: TASK=test
- node_js: 5
env: TASK=test
- node_js: 6
env: TASK=test
- node_js: 7
env: TASK=test
- node_js: 8
env: TASK=test
- node_js: 9
env: TASK=test
script: "npm run $TASK"
env:
global:
- secure: rE2Vvo7vnjabYNULNyLFxOyt98BoJexDqsiOnfiD6kLYYsiQGfr/sbZkPMOFm9qfQG7pjqx+zZWZjGSswhTt+626C0t/njXqug7Yps4c3dFblzGfreQHp7wNX5TFsvrxd6dAowVasMp61sJcRnB2w8cUzoe3RAYUDHyiHktwqMc=
- secure: g9YINaKAdMatsJ28G9jCGbSaguXCyxSTy+pBO6Ch0Cf57ZLOTka3HqDj8p3nV28LUIHZ3ut5WO43CeYKwt4AUtLpBS3a0dndHdY6D83uY6b2qh5hXlrcbeQTq2cvw2y95F7hm4D1kwrgZ7ViqaKggRcEupAL69YbJnxeUDKWEdI=

View File

@ -0,0 +1,38 @@
# Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
* (a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
* (b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
* (c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
* (d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
## Moderation Policy
The [Node.js Moderation Policy] applies to this WG.
## Code of Conduct
The [Node.js Code of Conduct][] applies to this WG.
[Node.js Code of Conduct]:
https://github.com/nodejs/node/blob/master/CODE_OF_CONDUCT.md
[Node.js Moderation Policy]:
https://github.com/nodejs/TSC/blob/master/Moderation-Policy.md

View File

@ -0,0 +1,136 @@
### Streams Working Group
The Node.js Streams is jointly governed by a Working Group
(WG)
that is responsible for high-level guidance of the project.
The WG has final authority over this project including:
* Technical direction
* Project governance and process (including this policy)
* Contribution policy
* GitHub repository hosting
* Conduct guidelines
* Maintaining the list of additional Collaborators
For the current list of WG members, see the project
[README.md](./README.md#current-project-team-members).
### Collaborators
The readable-stream GitHub repository is
maintained by the WG and additional Collaborators who are added by the
WG on an ongoing basis.
Individuals making significant and valuable contributions are made
Collaborators and given commit-access to the project. These
individuals are identified by the WG and their addition as
Collaborators is discussed during the WG meeting.
_Note:_ If you make a significant contribution and are not considered
for commit-access log an issue or contact a WG member directly and it
will be brought up in the next WG meeting.
Modifications of the contents of the readable-stream repository are
made on
a collaborative basis. Anybody with a GitHub account may propose a
modification via pull request and it will be considered by the project
Collaborators. All pull requests must be reviewed and accepted by a
Collaborator with sufficient expertise who is able to take full
responsibility for the change. In the case of pull requests proposed
by an existing Collaborator, an additional Collaborator is required
for sign-off. Consensus should be sought if additional Collaborators
participate and there is disagreement around a particular
modification. See _Consensus Seeking Process_ below for further detail
on the consensus model used for governance.
Collaborators may opt to elevate significant or controversial
modifications, or modifications that have not found consensus to the
WG for discussion by assigning the ***WG-agenda*** tag to a pull
request or issue. The WG should serve as the final arbiter where
required.
For the current list of Collaborators, see the project
[README.md](./README.md#members).
### WG Membership
WG seats are not time-limited. There is no fixed size of the WG.
However, the expected target is between 6 and 12, to ensure adequate
coverage of important areas of expertise, balanced with the ability to
make decisions efficiently.
There is no specific set of requirements or qualifications for WG
membership beyond these rules.
The WG may add additional members to the WG by unanimous consensus.
A WG member may be removed from the WG by voluntary resignation, or by
unanimous consensus of all other WG members.
Changes to WG membership should be posted in the agenda, and may be
suggested as any other agenda item (see "WG Meetings" below).
If an addition or removal is proposed during a meeting, and the full
WG is not in attendance to participate, then the addition or removal
is added to the agenda for the subsequent meeting. This is to ensure
that all members are given the opportunity to participate in all
membership decisions. If a WG member is unable to attend a meeting
where a planned membership decision is being made, then their consent
is assumed.
No more than 1/3 of the WG members may be affiliated with the same
employer. If removal or resignation of a WG member, or a change of
employment by a WG member, creates a situation where more than 1/3 of
the WG membership shares an employer, then the situation must be
immediately remedied by the resignation or removal of one or more WG
members affiliated with the over-represented employer(s).
### WG Meetings
The WG meets occasionally on a Google Hangout On Air. A designated moderator
approved by the WG runs the meeting. Each meeting should be
published to YouTube.
Items are added to the WG agenda that are considered contentious or
are modifications of governance, contribution policy, WG membership,
or release process.
The intention of the agenda is not to approve or review all patches;
that should happen continuously on GitHub and be handled by the larger
group of Collaborators.
Any community member or contributor can ask that something be added to
the next meeting's agenda by logging a GitHub Issue. Any Collaborator,
WG member or the moderator can add the item to the agenda by adding
the ***WG-agenda*** tag to the issue.
Prior to each WG meeting the moderator will share the Agenda with
members of the WG. WG members can add any items they like to the
agenda at the beginning of each meeting. The moderator and the WG
cannot veto or remove items.
The WG may invite persons or representatives from certain projects to
participate in a non-voting capacity.
The moderator is responsible for summarizing the discussion of each
agenda item and sends it as a pull request after the meeting.
### Consensus Seeking Process
The WG follows a
[Consensus
Seeking](http://en.wikipedia.org/wiki/Consensus-seeking_decision-making)
decision-making model.
When an agenda item has appeared to reach a consensus the moderator
will ask "Does anyone object?" as a final call for dissent from the
consensus.
If an agenda item cannot reach a consensus a WG member can call for
either a closing vote or a vote to table the issue to the next
meeting. The call for a vote must be seconded by a majority of the WG
or else the discussion will continue. Simple majority wins.
Note that changes to WG membership require a majority consensus. See
"WG Membership" above.

View File

@ -0,0 +1,47 @@
Node.js is licensed for use as follows:
"""
Copyright Node.js contributors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
"""
This license applies to parts of Node.js originating from the
https://github.com/joyent/node repository:
"""
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
"""

View File

@ -0,0 +1,58 @@
# readable-stream
***Node-core v8.11.1 streams for userland*** [![Build Status](https://travis-ci.org/nodejs/readable-stream.svg?branch=master)](https://travis-ci.org/nodejs/readable-stream)
[![NPM](https://nodei.co/npm/readable-stream.png?downloads=true&downloadRank=true)](https://nodei.co/npm/readable-stream/)
[![NPM](https://nodei.co/npm-dl/readable-stream.png?&months=6&height=3)](https://nodei.co/npm/readable-stream/)
[![Sauce Test Status](https://saucelabs.com/browser-matrix/readable-stream.svg)](https://saucelabs.com/u/readable-stream)
```bash
npm install --save readable-stream
```
***Node-core streams for userland***
This package is a mirror of the Streams2 and Streams3 implementations in
Node-core.
Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v8.11.1/docs/api/stream.html).
If you want to guarantee a stable streams base, regardless of what version of
Node you, or the users of your libraries are using, use **readable-stream** *only* and avoid the *"stream"* module in Node-core, for background see [this blogpost](http://r.va.gg/2014/06/why-i-dont-use-nodes-core-stream-module.html).
As of version 2.0.0 **readable-stream** uses semantic versioning.
# Streams Working Group
`readable-stream` is maintained by the Streams Working Group, which
oversees the development and maintenance of the Streams API within
Node.js. The responsibilities of the Streams Working Group include:
* Addressing stream issues on the Node.js issue tracker.
* Authoring and editing stream documentation within the Node.js project.
* Reviewing changes to stream subclasses within the Node.js project.
* Redirecting changes to streams from the Node.js project to this
project.
* Assisting in the implementation of stream providers within Node.js.
* Recommending versions of `readable-stream` to be included in Node.js.
* Messaging about the future of streams to give the community advance
notice of changes.
<a name="members"></a>
## Team Members
* **Chris Dickinson** ([@chrisdickinson](https://github.com/chrisdickinson)) &lt;christopher.s.dickinson@gmail.com&gt;
- Release GPG key: 9554F04D7259F04124DE6B476D5A82AC7E37093B
* **Calvin Metcalf** ([@calvinmetcalf](https://github.com/calvinmetcalf)) &lt;calvin.metcalf@gmail.com&gt;
- Release GPG key: F3EF5F62A87FC27A22E643F714CE4FF5015AA242
* **Rod Vagg** ([@rvagg](https://github.com/rvagg)) &lt;rod@vagg.org&gt;
- Release GPG key: DD8F2338BAE7501E3DD5AC78C273792F7D83545D
* **Sam Newman** ([@sonewman](https://github.com/sonewman)) &lt;newmansam@outlook.com&gt;
* **Mathias Buus** ([@mafintosh](https://github.com/mafintosh)) &lt;mathiasbuus@gmail.com&gt;
* **Domenic Denicola** ([@domenic](https://github.com/domenic)) &lt;d@domenic.me&gt;
* **Matteo Collina** ([@mcollina](https://github.com/mcollina)) &lt;matteo.collina@gmail.com&gt;
- Release GPG key: 3ABC01543F22DD2239285CDD818674489FBC127E
* **Irina Shestak** ([@lrlna](https://github.com/lrlna)) &lt;shestak.irina@gmail.com&gt;

View File

@ -0,0 +1,60 @@
# streams WG Meeting 2015-01-30
## Links
* **Google Hangouts Video**: http://www.youtube.com/watch?v=I9nDOSGfwZg
* **GitHub Issue**: https://github.com/iojs/readable-stream/issues/106
* **Original Minutes Google Doc**: https://docs.google.com/document/d/17aTgLnjMXIrfjgNaTUnHQO7m3xgzHR2VXBTmi03Qii4/
## Agenda
Extracted from https://github.com/iojs/readable-stream/labels/wg-agenda prior to meeting.
* adopt a charter [#105](https://github.com/iojs/readable-stream/issues/105)
* release and versioning strategy [#101](https://github.com/iojs/readable-stream/issues/101)
* simpler stream creation [#102](https://github.com/iojs/readable-stream/issues/102)
* proposal: deprecate implicit flowing of streams [#99](https://github.com/iojs/readable-stream/issues/99)
## Minutes
### adopt a charter
* group: +1's all around
### What versioning scheme should be adopted?
* group: +1s 3.0.0
* domenic+group: pulling in patches from other sources where appropriate
* mikeal: version independently, suggesting versions for io.js
* mikeal+domenic: work with TC to notify in advance of changes
simpler stream creation
### streamline creation of streams
* sam: streamline creation of streams
* domenic: nice simple solution posted
but, we lose the opportunity to change the model
may not be backwards incompatible (double check keys)
**action item:** domenic will check
### remove implicit flowing of streams on(data)
* add isFlowing / isPaused
* mikeal: worrying that were documenting polyfill methods confuses users
* domenic: more reflective API is probably good, with warning labels for users
* new section for mad scientists (reflective stream access)
* calvin: name the “third state”
* mikeal: maybe borrow the name from whatwg?
* domenic: were missing the “third state”
* consensus: kind of difficult to name the third state
* mikeal: figure out differences in states / compat
* mathias: always flow on data eliminates third state
* explore what it breaks
**action items:**
* ask isaac for ability to list packages by what public io.js APIs they use (esp. Stream)
* ask rod/build for infrastructure
* **chris**: explore the “flow on data” approach
* add isPaused/isFlowing
* add new docs section
* move isPaused to that section

View File

@ -0,0 +1 @@
module.exports = require('./lib/_stream_duplex.js');

View File

@ -0,0 +1 @@
module.exports = require('./readable').Duplex

View File

@ -0,0 +1,131 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
// a duplex stream is just a stream that is both readable and writable.
// Since JS doesn't have multiple prototypal inheritance, this class
// prototypally inherits from Readable, and then parasitically from
// Writable.
'use strict';
/*<replacement>*/
var pna = require('process-nextick-args');
/*</replacement>*/
/*<replacement>*/
var objectKeys = Object.keys || function (obj) {
var keys = [];
for (var key in obj) {
keys.push(key);
}return keys;
};
/*</replacement>*/
module.exports = Duplex;
/*<replacement>*/
var util = require('core-util-is');
util.inherits = require('inherits');
/*</replacement>*/
var Readable = require('./_stream_readable');
var Writable = require('./_stream_writable');
util.inherits(Duplex, Readable);
{
// avoid scope creep, the keys array can then be collected
var keys = objectKeys(Writable.prototype);
for (var v = 0; v < keys.length; v++) {
var method = keys[v];
if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method];
}
}
function Duplex(options) {
if (!(this instanceof Duplex)) return new Duplex(options);
Readable.call(this, options);
Writable.call(this, options);
if (options && options.readable === false) this.readable = false;
if (options && options.writable === false) this.writable = false;
this.allowHalfOpen = true;
if (options && options.allowHalfOpen === false) this.allowHalfOpen = false;
this.once('end', onend);
}
Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', {
// making it explicit this property is not enumerable
// because otherwise some prototype manipulation in
// userland will fail
enumerable: false,
get: function () {
return this._writableState.highWaterMark;
}
});
// the no-half-open enforcer
function onend() {
// if we allow half-open state, or if the writable side ended,
// then we're ok.
if (this.allowHalfOpen || this._writableState.ended) return;
// no more data can be written.
// But allow more writes to happen in this tick.
pna.nextTick(onEndNT, this);
}
function onEndNT(self) {
self.end();
}
Object.defineProperty(Duplex.prototype, 'destroyed', {
get: function () {
if (this._readableState === undefined || this._writableState === undefined) {
return false;
}
return this._readableState.destroyed && this._writableState.destroyed;
},
set: function (value) {
// we ignore the value if the stream
// has not been initialized yet
if (this._readableState === undefined || this._writableState === undefined) {
return;
}
// backward compatibility, the user is explicitly
// managing destroyed
this._readableState.destroyed = value;
this._writableState.destroyed = value;
}
});
Duplex.prototype._destroy = function (err, cb) {
this.push(null);
this.end();
pna.nextTick(cb, err);
};

View File

@ -0,0 +1,47 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
// a passthrough stream.
// basically just the most minimal sort of Transform stream.
// Every written chunk gets output as-is.
'use strict';
module.exports = PassThrough;
var Transform = require('./_stream_transform');
/*<replacement>*/
var util = require('core-util-is');
util.inherits = require('inherits');
/*</replacement>*/
util.inherits(PassThrough, Transform);
function PassThrough(options) {
if (!(this instanceof PassThrough)) return new PassThrough(options);
Transform.call(this, options);
}
PassThrough.prototype._transform = function (chunk, encoding, cb) {
cb(null, chunk);
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,214 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
// a transform stream is a readable/writable stream where you do
// something with the data. Sometimes it's called a "filter",
// but that's not a great name for it, since that implies a thing where
// some bits pass through, and others are simply ignored. (That would
// be a valid example of a transform, of course.)
//
// While the output is causally related to the input, it's not a
// necessarily symmetric or synchronous transformation. For example,
// a zlib stream might take multiple plain-text writes(), and then
// emit a single compressed chunk some time in the future.
//
// Here's how this works:
//
// The Transform stream has all the aspects of the readable and writable
// stream classes. When you write(chunk), that calls _write(chunk,cb)
// internally, and returns false if there's a lot of pending writes
// buffered up. When you call read(), that calls _read(n) until
// there's enough pending readable data buffered up.
//
// In a transform stream, the written data is placed in a buffer. When
// _read(n) is called, it transforms the queued up data, calling the
// buffered _write cb's as it consumes chunks. If consuming a single
// written chunk would result in multiple output chunks, then the first
// outputted bit calls the readcb, and subsequent chunks just go into
// the read buffer, and will cause it to emit 'readable' if necessary.
//
// This way, back-pressure is actually determined by the reading side,
// since _read has to be called to start processing a new chunk. However,
// a pathological inflate type of transform can cause excessive buffering
// here. For example, imagine a stream where every byte of input is
// interpreted as an integer from 0-255, and then results in that many
// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in
// 1kb of data being output. In this case, you could write a very small
// amount of input, and end up with a very large amount of output. In
// such a pathological inflating mechanism, there'd be no way to tell
// the system to stop doing the transform. A single 4MB write could
// cause the system to run out of memory.
//
// However, even in such a pathological case, only a single written chunk
// would be consumed, and then the rest would wait (un-transformed) until
// the results of the previous transformed chunk were consumed.
'use strict';
module.exports = Transform;
var Duplex = require('./_stream_duplex');
/*<replacement>*/
var util = require('core-util-is');
util.inherits = require('inherits');
/*</replacement>*/
util.inherits(Transform, Duplex);
function afterTransform(er, data) {
var ts = this._transformState;
ts.transforming = false;
var cb = ts.writecb;
if (!cb) {
return this.emit('error', new Error('write callback called multiple times'));
}
ts.writechunk = null;
ts.writecb = null;
if (data != null) // single equals check for both `null` and `undefined`
this.push(data);
cb(er);
var rs = this._readableState;
rs.reading = false;
if (rs.needReadable || rs.length < rs.highWaterMark) {
this._read(rs.highWaterMark);
}
}
function Transform(options) {
if (!(this instanceof Transform)) return new Transform(options);
Duplex.call(this, options);
this._transformState = {
afterTransform: afterTransform.bind(this),
needTransform: false,
transforming: false,
writecb: null,
writechunk: null,
writeencoding: null
};
// start out asking for a readable event once data is transformed.
this._readableState.needReadable = true;
// we have implemented the _read method, and done the other things
// that Readable wants before the first _read call, so unset the
// sync guard flag.
this._readableState.sync = false;
if (options) {
if (typeof options.transform === 'function') this._transform = options.transform;
if (typeof options.flush === 'function') this._flush = options.flush;
}
// When the writable side finishes, then flush out anything remaining.
this.on('prefinish', prefinish);
}
function prefinish() {
var _this = this;
if (typeof this._flush === 'function') {
this._flush(function (er, data) {
done(_this, er, data);
});
} else {
done(this, null, null);
}
}
Transform.prototype.push = function (chunk, encoding) {
this._transformState.needTransform = false;
return Duplex.prototype.push.call(this, chunk, encoding);
};
// This is the part where you do stuff!
// override this function in implementation classes.
// 'chunk' is an input chunk.
//
// Call `push(newChunk)` to pass along transformed output
// to the readable side. You may call 'push' zero or more times.
//
// Call `cb(err)` when you are done with this chunk. If you pass
// an error, then that'll put the hurt on the whole operation. If you
// never call cb(), then you'll never get another chunk.
Transform.prototype._transform = function (chunk, encoding, cb) {
throw new Error('_transform() is not implemented');
};
Transform.prototype._write = function (chunk, encoding, cb) {
var ts = this._transformState;
ts.writecb = cb;
ts.writechunk = chunk;
ts.writeencoding = encoding;
if (!ts.transforming) {
var rs = this._readableState;
if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark);
}
};
// Doesn't matter what the args are here.
// _transform does all the work.
// That we got here means that the readable side wants more data.
Transform.prototype._read = function (n) {
var ts = this._transformState;
if (ts.writechunk !== null && ts.writecb && !ts.transforming) {
ts.transforming = true;
this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
} else {
// mark that we need a transform, so that any data that comes in
// will get processed, now that we've asked for it.
ts.needTransform = true;
}
};
Transform.prototype._destroy = function (err, cb) {
var _this2 = this;
Duplex.prototype._destroy.call(this, err, function (err2) {
cb(err2);
_this2.emit('close');
});
};
function done(stream, er, data) {
if (er) return stream.emit('error', er);
if (data != null) // single equals check for both `null` and `undefined`
stream.push(data);
// if there's nothing in the write buffer, then that means
// that nothing more will ever be provided
if (stream._writableState.length) throw new Error('Calling transform done when ws.length != 0');
if (stream._transformState.transforming) throw new Error('Calling transform done when still transforming');
return stream.push(null);
}

View File

@ -0,0 +1,687 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
// A bit simpler than readable streams.
// Implement an async ._write(chunk, encoding, cb), and it'll handle all
// the drain event emission and buffering.
'use strict';
/*<replacement>*/
var pna = require('process-nextick-args');
/*</replacement>*/
module.exports = Writable;
/* <replacement> */
function WriteReq(chunk, encoding, cb) {
this.chunk = chunk;
this.encoding = encoding;
this.callback = cb;
this.next = null;
}
// It seems a linked list but it is not
// there will be only 2 of these for each stream
function CorkedRequest(state) {
var _this = this;
this.next = null;
this.entry = null;
this.finish = function () {
onCorkedFinish(_this, state);
};
}
/* </replacement> */
/*<replacement>*/
var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick;
/*</replacement>*/
/*<replacement>*/
var Duplex;
/*</replacement>*/
Writable.WritableState = WritableState;
/*<replacement>*/
var util = require('core-util-is');
util.inherits = require('inherits');
/*</replacement>*/
/*<replacement>*/
var internalUtil = {
deprecate: require('util-deprecate')
};
/*</replacement>*/
/*<replacement>*/
var Stream = require('./internal/streams/stream');
/*</replacement>*/
/*<replacement>*/
var Buffer = require('safe-buffer').Buffer;
var OurUint8Array = global.Uint8Array || function () {};
function _uint8ArrayToBuffer(chunk) {
return Buffer.from(chunk);
}
function _isUint8Array(obj) {
return Buffer.isBuffer(obj) || obj instanceof OurUint8Array;
}
/*</replacement>*/
var destroyImpl = require('./internal/streams/destroy');
util.inherits(Writable, Stream);
function nop() {}
function WritableState(options, stream) {
Duplex = Duplex || require('./_stream_duplex');
options = options || {};
// Duplex streams are both readable and writable, but share
// the same options object.
// However, some cases require setting options to different
// values for the readable and the writable sides of the duplex stream.
// These options can be provided separately as readableXXX and writableXXX.
var isDuplex = stream instanceof Duplex;
// object stream flag to indicate whether or not this stream
// contains buffers or objects.
this.objectMode = !!options.objectMode;
if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode;
// the point at which write() starts returning false
// Note: 0 is a valid value, means that we always return false if
// the entire buffer is not flushed immediately on write()
var hwm = options.highWaterMark;
var writableHwm = options.writableHighWaterMark;
var defaultHwm = this.objectMode ? 16 : 16 * 1024;
if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (writableHwm || writableHwm === 0)) this.highWaterMark = writableHwm;else this.highWaterMark = defaultHwm;
// cast to ints.
this.highWaterMark = Math.floor(this.highWaterMark);
// if _final has been called
this.finalCalled = false;
// drain event flag.
this.needDrain = false;
// at the start of calling end()
this.ending = false;
// when end() has been called, and returned
this.ended = false;
// when 'finish' is emitted
this.finished = false;
// has it been destroyed
this.destroyed = false;
// should we decode strings into buffers before passing to _write?
// this is here so that some node-core streams can optimize string
// handling at a lower level.
var noDecode = options.decodeStrings === false;
this.decodeStrings = !noDecode;
// Crypto is kind of old and crusty. Historically, its default string
// encoding is 'binary' so we have to make this configurable.
// Everything else in the universe uses 'utf8', though.
this.defaultEncoding = options.defaultEncoding || 'utf8';
// not an actual buffer we keep track of, but a measurement
// of how much we're waiting to get pushed to some underlying
// socket or file.
this.length = 0;
// a flag to see when we're in the middle of a write.
this.writing = false;
// when true all writes will be buffered until .uncork() call
this.corked = 0;
// a flag to be able to tell if the onwrite cb is called immediately,
// or on a later tick. We set this to true at first, because any
// actions that shouldn't happen until "later" should generally also
// not happen before the first write call.
this.sync = true;
// a flag to know if we're processing previously buffered items, which
// may call the _write() callback in the same tick, so that we don't
// end up in an overlapped onwrite situation.
this.bufferProcessing = false;
// the callback that's passed to _write(chunk,cb)
this.onwrite = function (er) {
onwrite(stream, er);
};
// the callback that the user supplies to write(chunk,encoding,cb)
this.writecb = null;
// the amount that is being written when _write is called.
this.writelen = 0;
this.bufferedRequest = null;
this.lastBufferedRequest = null;
// number of pending user-supplied write callbacks
// this must be 0 before 'finish' can be emitted
this.pendingcb = 0;
// emit prefinish if the only thing we're waiting for is _write cbs
// This is relevant for synchronous Transform streams
this.prefinished = false;
// True if the error was already emitted and should not be thrown again
this.errorEmitted = false;
// count buffered requests
this.bufferedRequestCount = 0;
// allocate the first CorkedRequest, there is always
// one allocated and free to use, and we maintain at most two
this.corkedRequestsFree = new CorkedRequest(this);
}
WritableState.prototype.getBuffer = function getBuffer() {
var current = this.bufferedRequest;
var out = [];
while (current) {
out.push(current);
current = current.next;
}
return out;
};
(function () {
try {
Object.defineProperty(WritableState.prototype, 'buffer', {
get: internalUtil.deprecate(function () {
return this.getBuffer();
}, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003')
});
} catch (_) {}
})();
// Test _writableState for inheritance to account for Duplex streams,
// whose prototype chain only points to Readable.
var realHasInstance;
if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') {
realHasInstance = Function.prototype[Symbol.hasInstance];
Object.defineProperty(Writable, Symbol.hasInstance, {
value: function (object) {
if (realHasInstance.call(this, object)) return true;
if (this !== Writable) return false;
return object && object._writableState instanceof WritableState;
}
});
} else {
realHasInstance = function (object) {
return object instanceof this;
};
}
function Writable(options) {
Duplex = Duplex || require('./_stream_duplex');
// Writable ctor is applied to Duplexes, too.
// `realHasInstance` is necessary because using plain `instanceof`
// would return false, as no `_writableState` property is attached.
// Trying to use the custom `instanceof` for Writable here will also break the
// Node.js LazyTransform implementation, which has a non-trivial getter for
// `_writableState` that would lead to infinite recursion.
if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) {
return new Writable(options);
}
this._writableState = new WritableState(options, this);
// legacy.
this.writable = true;
if (options) {
if (typeof options.write === 'function') this._write = options.write;
if (typeof options.writev === 'function') this._writev = options.writev;
if (typeof options.destroy === 'function') this._destroy = options.destroy;
if (typeof options.final === 'function') this._final = options.final;
}
Stream.call(this);
}
// Otherwise people can pipe Writable streams, which is just wrong.
Writable.prototype.pipe = function () {
this.emit('error', new Error('Cannot pipe, not readable'));
};
function writeAfterEnd(stream, cb) {
var er = new Error('write after end');
// TODO: defer error events consistently everywhere, not just the cb
stream.emit('error', er);
pna.nextTick(cb, er);
}
// Checks that a user-supplied chunk is valid, especially for the particular
// mode the stream is in. Currently this means that `null` is never accepted
// and undefined/non-string values are only allowed in object mode.
function validChunk(stream, state, chunk, cb) {
var valid = true;
var er = false;
if (chunk === null) {
er = new TypeError('May not write null values to stream');
} else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) {
er = new TypeError('Invalid non-string/buffer chunk');
}
if (er) {
stream.emit('error', er);
pna.nextTick(cb, er);
valid = false;
}
return valid;
}
Writable.prototype.write = function (chunk, encoding, cb) {
var state = this._writableState;
var ret = false;
var isBuf = !state.objectMode && _isUint8Array(chunk);
if (isBuf && !Buffer.isBuffer(chunk)) {
chunk = _uint8ArrayToBuffer(chunk);
}
if (typeof encoding === 'function') {
cb = encoding;
encoding = null;
}
if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding;
if (typeof cb !== 'function') cb = nop;
if (state.ended) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) {
state.pendingcb++;
ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb);
}
return ret;
};
Writable.prototype.cork = function () {
var state = this._writableState;
state.corked++;
};
Writable.prototype.uncork = function () {
var state = this._writableState;
if (state.corked) {
state.corked--;
if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state);
}
};
Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
// node::ParseEncoding() requires lower case.
if (typeof encoding === 'string') encoding = encoding.toLowerCase();
if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding);
this._writableState.defaultEncoding = encoding;
return this;
};
function decodeChunk(state, chunk, encoding) {
if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') {
chunk = Buffer.from(chunk, encoding);
}
return chunk;
}
Object.defineProperty(Writable.prototype, 'writableHighWaterMark', {
// making it explicit this property is not enumerable
// because otherwise some prototype manipulation in
// userland will fail
enumerable: false,
get: function () {
return this._writableState.highWaterMark;
}
});
// if we're already writing something, then just put this
// in the queue, and wait our turn. Otherwise, call _write
// If we return false, then we need a drain event, so set that flag.
function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) {
if (!isBuf) {
var newChunk = decodeChunk(state, chunk, encoding);
if (chunk !== newChunk) {
isBuf = true;
encoding = 'buffer';
chunk = newChunk;
}
}
var len = state.objectMode ? 1 : chunk.length;
state.length += len;
var ret = state.length < state.highWaterMark;
// we must ensure that previous needDrain will not be reset to false.
if (!ret) state.needDrain = true;
if (state.writing || state.corked) {
var last = state.lastBufferedRequest;
state.lastBufferedRequest = {
chunk: chunk,
encoding: encoding,
isBuf: isBuf,
callback: cb,
next: null
};
if (last) {
last.next = state.lastBufferedRequest;
} else {
state.bufferedRequest = state.lastBufferedRequest;
}
state.bufferedRequestCount += 1;
} else {
doWrite(stream, state, false, len, chunk, encoding, cb);
}
return ret;
}
function doWrite(stream, state, writev, len, chunk, encoding, cb) {
state.writelen = len;
state.writecb = cb;
state.writing = true;
state.sync = true;
if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite);
state.sync = false;
}
function onwriteError(stream, state, sync, er, cb) {
--state.pendingcb;
if (sync) {
// defer the callback if we are being called synchronously
// to avoid piling up things on the stack
pna.nextTick(cb, er);
// this can emit finish, and it will always happen
// after error
pna.nextTick(finishMaybe, stream, state);
stream._writableState.errorEmitted = true;
stream.emit('error', er);
} else {
// the caller expect this to happen before if
// it is async
cb(er);
stream._writableState.errorEmitted = true;
stream.emit('error', er);
// this can emit finish, but finish must
// always follow error
finishMaybe(stream, state);
}
}
function onwriteStateUpdate(state) {
state.writing = false;
state.writecb = null;
state.length -= state.writelen;
state.writelen = 0;
}
function onwrite(stream, er) {
var state = stream._writableState;
var sync = state.sync;
var cb = state.writecb;
onwriteStateUpdate(state);
if (er) onwriteError(stream, state, sync, er, cb);else {
// Check if we're actually ready to finish, but don't emit yet
var finished = needFinish(state);
if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) {
clearBuffer(stream, state);
}
if (sync) {
/*<replacement>*/
asyncWrite(afterWrite, stream, state, finished, cb);
/*</replacement>*/
} else {
afterWrite(stream, state, finished, cb);
}
}
}
function afterWrite(stream, state, finished, cb) {
if (!finished) onwriteDrain(stream, state);
state.pendingcb--;
cb();
finishMaybe(stream, state);
}
// Must force callback to be called on nextTick, so that we don't
// emit 'drain' before the write() consumer gets the 'false' return
// value, and has a chance to attach a 'drain' listener.
function onwriteDrain(stream, state) {
if (state.length === 0 && state.needDrain) {
state.needDrain = false;
stream.emit('drain');
}
}
// if there's something in the buffer waiting, then process it
function clearBuffer(stream, state) {
state.bufferProcessing = true;
var entry = state.bufferedRequest;
if (stream._writev && entry && entry.next) {
// Fast case, write everything using _writev()
var l = state.bufferedRequestCount;
var buffer = new Array(l);
var holder = state.corkedRequestsFree;
holder.entry = entry;
var count = 0;
var allBuffers = true;
while (entry) {
buffer[count] = entry;
if (!entry.isBuf) allBuffers = false;
entry = entry.next;
count += 1;
}
buffer.allBuffers = allBuffers;
doWrite(stream, state, true, state.length, buffer, '', holder.finish);
// doWrite is almost always async, defer these to save a bit of time
// as the hot path ends with doWrite
state.pendingcb++;
state.lastBufferedRequest = null;
if (holder.next) {
state.corkedRequestsFree = holder.next;
holder.next = null;
} else {
state.corkedRequestsFree = new CorkedRequest(state);
}
state.bufferedRequestCount = 0;
} else {
// Slow case, write chunks one-by-one
while (entry) {
var chunk = entry.chunk;
var encoding = entry.encoding;
var cb = entry.callback;
var len = state.objectMode ? 1 : chunk.length;
doWrite(stream, state, false, len, chunk, encoding, cb);
entry = entry.next;
state.bufferedRequestCount--;
// if we didn't call the onwrite immediately, then
// it means that we need to wait until it does.
// also, that means that the chunk and cb are currently
// being processed, so move the buffer counter past them.
if (state.writing) {
break;
}
}
if (entry === null) state.lastBufferedRequest = null;
}
state.bufferedRequest = entry;
state.bufferProcessing = false;
}
Writable.prototype._write = function (chunk, encoding, cb) {
cb(new Error('_write() is not implemented'));
};
Writable.prototype._writev = null;
Writable.prototype.end = function (chunk, encoding, cb) {
var state = this._writableState;
if (typeof chunk === 'function') {
cb = chunk;
chunk = null;
encoding = null;
} else if (typeof encoding === 'function') {
cb = encoding;
encoding = null;
}
if (chunk !== null && chunk !== undefined) this.write(chunk, encoding);
// .end() fully uncorks
if (state.corked) {
state.corked = 1;
this.uncork();
}
// ignore unnecessary end() calls.
if (!state.ending && !state.finished) endWritable(this, state, cb);
};
function needFinish(state) {
return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing;
}
function callFinal(stream, state) {
stream._final(function (err) {
state.pendingcb--;
if (err) {
stream.emit('error', err);
}
state.prefinished = true;
stream.emit('prefinish');
finishMaybe(stream, state);
});
}
function prefinish(stream, state) {
if (!state.prefinished && !state.finalCalled) {
if (typeof stream._final === 'function') {
state.pendingcb++;
state.finalCalled = true;
pna.nextTick(callFinal, stream, state);
} else {
state.prefinished = true;
stream.emit('prefinish');
}
}
}
function finishMaybe(stream, state) {
var need = needFinish(state);
if (need) {
prefinish(stream, state);
if (state.pendingcb === 0) {
state.finished = true;
stream.emit('finish');
}
}
return need;
}
function endWritable(stream, state, cb) {
state.ending = true;
finishMaybe(stream, state);
if (cb) {
if (state.finished) pna.nextTick(cb);else stream.once('finish', cb);
}
state.ended = true;
stream.writable = false;
}
function onCorkedFinish(corkReq, state, err) {
var entry = corkReq.entry;
corkReq.entry = null;
while (entry) {
var cb = entry.callback;
state.pendingcb--;
cb(err);
entry = entry.next;
}
if (state.corkedRequestsFree) {
state.corkedRequestsFree.next = corkReq;
} else {
state.corkedRequestsFree = corkReq;
}
}
Object.defineProperty(Writable.prototype, 'destroyed', {
get: function () {
if (this._writableState === undefined) {
return false;
}
return this._writableState.destroyed;
},
set: function (value) {
// we ignore the value if the stream
// has not been initialized yet
if (!this._writableState) {
return;
}
// backward compatibility, the user is explicitly
// managing destroyed
this._writableState.destroyed = value;
}
});
Writable.prototype.destroy = destroyImpl.destroy;
Writable.prototype._undestroy = destroyImpl.undestroy;
Writable.prototype._destroy = function (err, cb) {
this.end();
cb(err);
};

View File

@ -0,0 +1,79 @@
'use strict';
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Buffer = require('safe-buffer').Buffer;
var util = require('util');
function copyBuffer(src, target, offset) {
src.copy(target, offset);
}
module.exports = function () {
function BufferList() {
_classCallCheck(this, BufferList);
this.head = null;
this.tail = null;
this.length = 0;
}
BufferList.prototype.push = function push(v) {
var entry = { data: v, next: null };
if (this.length > 0) this.tail.next = entry;else this.head = entry;
this.tail = entry;
++this.length;
};
BufferList.prototype.unshift = function unshift(v) {
var entry = { data: v, next: this.head };
if (this.length === 0) this.tail = entry;
this.head = entry;
++this.length;
};
BufferList.prototype.shift = function shift() {
if (this.length === 0) return;
var ret = this.head.data;
if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next;
--this.length;
return ret;
};
BufferList.prototype.clear = function clear() {
this.head = this.tail = null;
this.length = 0;
};
BufferList.prototype.join = function join(s) {
if (this.length === 0) return '';
var p = this.head;
var ret = '' + p.data;
while (p = p.next) {
ret += s + p.data;
}return ret;
};
BufferList.prototype.concat = function concat(n) {
if (this.length === 0) return Buffer.alloc(0);
if (this.length === 1) return this.head.data;
var ret = Buffer.allocUnsafe(n >>> 0);
var p = this.head;
var i = 0;
while (p) {
copyBuffer(p.data, ret, i);
i += p.data.length;
p = p.next;
}
return ret;
};
return BufferList;
}();
if (util && util.inspect && util.inspect.custom) {
module.exports.prototype[util.inspect.custom] = function () {
var obj = util.inspect({ length: this.length });
return this.constructor.name + ' ' + obj;
};
}

View File

@ -0,0 +1,74 @@
'use strict';
/*<replacement>*/
var pna = require('process-nextick-args');
/*</replacement>*/
// undocumented cb() API, needed for core, not for public API
function destroy(err, cb) {
var _this = this;
var readableDestroyed = this._readableState && this._readableState.destroyed;
var writableDestroyed = this._writableState && this._writableState.destroyed;
if (readableDestroyed || writableDestroyed) {
if (cb) {
cb(err);
} else if (err && (!this._writableState || !this._writableState.errorEmitted)) {
pna.nextTick(emitErrorNT, this, err);
}
return this;
}
// we set destroyed to true before firing error callbacks in order
// to make it re-entrance safe in case destroy() is called within callbacks
if (this._readableState) {
this._readableState.destroyed = true;
}
// if this is a duplex stream mark the writable part as destroyed as well
if (this._writableState) {
this._writableState.destroyed = true;
}
this._destroy(err || null, function (err) {
if (!cb && err) {
pna.nextTick(emitErrorNT, _this, err);
if (_this._writableState) {
_this._writableState.errorEmitted = true;
}
} else if (cb) {
cb(err);
}
});
return this;
}
function undestroy() {
if (this._readableState) {
this._readableState.destroyed = false;
this._readableState.reading = false;
this._readableState.ended = false;
this._readableState.endEmitted = false;
}
if (this._writableState) {
this._writableState.destroyed = false;
this._writableState.ended = false;
this._writableState.ending = false;
this._writableState.finished = false;
this._writableState.errorEmitted = false;
}
}
function emitErrorNT(self, err) {
self.emit('error', err);
}
module.exports = {
destroy: destroy,
undestroy: undestroy
};

View File

@ -0,0 +1 @@
module.exports = require('events').EventEmitter;

View File

@ -0,0 +1 @@
module.exports = require('stream');

View File

@ -0,0 +1,81 @@
{
"_from": "readable-stream@~2.3.6",
"_id": "readable-stream@2.3.6",
"_inBundle": false,
"_integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"_location": "/@google-cloud/common/readable-stream",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "readable-stream@~2.3.6",
"name": "readable-stream",
"escapedName": "readable-stream",
"rawSpec": "~2.3.6",
"saveSpec": null,
"fetchSpec": "~2.3.6"
},
"_requiredBy": [
"/@google-cloud/common/through2"
],
"_resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"_shasum": "b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf",
"_spec": "readable-stream@~2.3.6",
"_where": "D:\\Desktop\\Git\\Firebase\\SmartShopperFirebase\\node_modules\\@google-cloud\\common\\node_modules\\through2",
"browser": {
"util": false,
"./readable.js": "./readable-browser.js",
"./writable.js": "./writable-browser.js",
"./duplex.js": "./duplex-browser.js",
"./lib/internal/streams/stream.js": "./lib/internal/streams/stream-browser.js"
},
"bugs": {
"url": "https://github.com/nodejs/readable-stream/issues"
},
"bundleDependencies": false,
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
},
"deprecated": false,
"description": "Streams3, a user-land copy of the stream library from Node.js",
"devDependencies": {
"assert": "^1.4.0",
"babel-polyfill": "^6.9.1",
"buffer": "^4.9.0",
"lolex": "^2.3.2",
"nyc": "^6.4.0",
"tap": "^0.7.0",
"tape": "^4.8.0"
},
"homepage": "https://github.com/nodejs/readable-stream#readme",
"keywords": [
"readable",
"stream",
"pipe"
],
"license": "MIT",
"main": "readable.js",
"name": "readable-stream",
"nyc": {
"include": [
"lib/**.js"
]
},
"repository": {
"type": "git",
"url": "git://github.com/nodejs/readable-stream.git"
},
"scripts": {
"ci": "tap test/parallel/*.js test/ours/*.js --tap | tee test.tap && node test/verify-dependencies.js",
"cover": "nyc npm test",
"report": "nyc report --reporter=lcov",
"test": "tap test/parallel/*.js test/ours/*.js && node test/verify-dependencies.js"
},
"version": "2.3.6"
}

View File

@ -0,0 +1 @@
module.exports = require('./readable').PassThrough

View File

@ -0,0 +1,7 @@
exports = module.exports = require('./lib/_stream_readable.js');
exports.Stream = exports;
exports.Readable = exports;
exports.Writable = require('./lib/_stream_writable.js');
exports.Duplex = require('./lib/_stream_duplex.js');
exports.Transform = require('./lib/_stream_transform.js');
exports.PassThrough = require('./lib/_stream_passthrough.js');

View File

@ -0,0 +1,19 @@
var Stream = require('stream');
if (process.env.READABLE_STREAM === 'disable' && Stream) {
module.exports = Stream;
exports = module.exports = Stream.Readable;
exports.Readable = Stream.Readable;
exports.Writable = Stream.Writable;
exports.Duplex = Stream.Duplex;
exports.Transform = Stream.Transform;
exports.PassThrough = Stream.PassThrough;
exports.Stream = Stream;
} else {
exports = module.exports = require('./lib/_stream_readable.js');
exports.Stream = Stream || exports;
exports.Readable = exports;
exports.Writable = require('./lib/_stream_writable.js');
exports.Duplex = require('./lib/_stream_duplex.js');
exports.Transform = require('./lib/_stream_transform.js');
exports.PassThrough = require('./lib/_stream_passthrough.js');
}

View File

@ -0,0 +1 @@
module.exports = require('./readable').Transform

View File

@ -0,0 +1 @@
module.exports = require('./lib/_stream_writable.js');

View File

@ -0,0 +1,8 @@
var Stream = require("stream")
var Writable = require("./lib/_stream_writable.js")
if (process.env.READABLE_STREAM === 'disable') {
module.exports = Stream && Stream.Writable || Writable
} else {
module.exports = Writable
}

View File

@ -0,0 +1,22 @@
declare module 'retry-request' {
import * as request from 'request';
namespace retryRequest {
function getNextRetryDelay(retryNumber: number): void;
interface Options {
objectMode?: boolean,
request?: typeof request,
retries?: number,
noResponseRetries?: number,
currentRetryAttempt?: number,
shouldRetryFn?: (response: request.RequestResponse) => boolean
}
}
function retryRequest(requestOpts: request.Options, opts: retryRequest.Options, callback?: request.RequestCallback)
: { abort: () => void };
function retryRequest(requestOpts: request.Options, callback?: request.RequestCallback)
: { abort: () => void };
export = retryRequest;
}

View File

@ -0,0 +1,209 @@
'use strict';
var request = require('request');
var through = require('through2');
var DEFAULTS = {
objectMode: false,
request: request,
retries: 2,
noResponseRetries: 2,
currentRetryAttempt: 0,
shouldRetryFn: function (response) {
var retryRanges = [
// https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
// 1xx - Retry (Informational, request still processing)
// 2xx - Do not retry (Success)
// 3xx - Do not retry (Redirect)
// 4xx - Do not retry (Client errors)
// 429 - Retry ("Too Many Requests")
// 5xx - Retry (Server errors)
[100, 199],
[429, 429],
[500, 599]
];
var statusCode = response.statusCode;
var range;
while ((range = retryRanges.shift())) {
if (statusCode >= range[0] && statusCode <= range[1]) {
// Not a successful status or redirect.
return true;
}
}
}
};
function retryRequest(requestOpts, opts, callback) {
var streamMode = typeof arguments[arguments.length - 1] !== 'function';
if (typeof opts === 'function') {
callback = opts;
}
opts = opts || DEFAULTS;
if (typeof opts.objectMode === 'undefined') {
opts.objectMode = DEFAULTS.objectMode;
}
if (typeof opts.request === 'undefined') {
opts.request = DEFAULTS.request;
}
if (typeof opts.retries !== 'number') {
opts.retries = DEFAULTS.retries;
}
if (typeof opts.currentRetryAttempt !== 'number') {
opts.currentRetryAttempt = DEFAULTS.currentRetryAttempt;
}
if (typeof opts.noResponseRetries !== 'number') {
opts.noResponseRetries = DEFAULTS.noResponseRetries;
}
if (typeof opts.shouldRetryFn !== 'function') {
opts.shouldRetryFn = DEFAULTS.shouldRetryFn;
}
var currentRetryAttempt = opts.currentRetryAttempt;
var numNoResponseAttempts = 0;
var streamResponseHandled = false;
var retryStream;
var requestStream;
var delayStream;
var activeRequest;
var retryRequest = {
abort: function () {
if (activeRequest && activeRequest.abort) {
activeRequest.abort();
}
}
};
if (streamMode) {
retryStream = through({ objectMode: opts.objectMode });
retryStream.abort = resetStreams;
}
if (currentRetryAttempt > 0) {
retryAfterDelay(currentRetryAttempt);
} else {
makeRequest();
}
if (streamMode) {
return retryStream;
} else {
return retryRequest;
}
function resetStreams() {
delayStream = null;
if (requestStream) {
requestStream.abort && requestStream.abort();
requestStream.cancel && requestStream.cancel();
if (requestStream.destroy) {
requestStream.destroy();
} else if (requestStream.end) {
requestStream.end();
}
}
}
function makeRequest() {
currentRetryAttempt++;
if (streamMode) {
streamResponseHandled = false;
delayStream = through({ objectMode: opts.objectMode });
requestStream = opts.request(requestOpts);
setImmediate(function () {
retryStream.emit('request');
});
requestStream
// gRPC via google-cloud-node can emit an `error` as well as a `response`
// Whichever it emits, we run with-- we can't run with both. That's what
// is up with the `streamResponseHandled` tracking.
.on('error', function (err) {
if (streamResponseHandled) {
return;
}
streamResponseHandled = true;
onResponse(err);
})
.on('response', function (resp, body) {
if (streamResponseHandled) {
return;
}
streamResponseHandled = true;
onResponse(null, resp, body);
})
.on('complete', retryStream.emit.bind(retryStream, 'complete'));
requestStream.pipe(delayStream);
} else {
activeRequest = opts.request(requestOpts, onResponse);
}
}
function retryAfterDelay(currentRetryAttempt) {
if (streamMode) {
resetStreams();
}
setTimeout(makeRequest, getNextRetryDelay(currentRetryAttempt));
}
function onResponse(err, response, body) {
// An error such as DNS resolution.
if (err) {
numNoResponseAttempts++;
if (numNoResponseAttempts <= opts.noResponseRetries) {
retryAfterDelay(numNoResponseAttempts);
} else {
if (streamMode) {
retryStream.emit('error', err);
retryStream.end();
} else {
callback(err, response, body);
}
}
return;
}
// Send the response to see if we should try again.
if (currentRetryAttempt <= opts.retries && opts.shouldRetryFn(response)) {
retryAfterDelay(currentRetryAttempt);
return;
}
// No more attempts need to be made, just continue on.
if (streamMode) {
retryStream.emit('response', response);
delayStream.pipe(retryStream);
requestStream.on('error', function (err) {
retryStream.destroy(err);
});
} else {
callback(err, response, body);
}
}
}
module.exports = retryRequest;
function getNextRetryDelay(retryNumber) {
return (Math.pow(2, retryNumber) * 1000) + Math.floor(Math.random() * 1000);
}
module.exports.getNextRetryDelay = getNextRetryDelay;

View File

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2015 Stephen Sawchuk
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,70 @@
{
"_from": "retry-request@^3.0.0",
"_id": "retry-request@3.3.2",
"_inBundle": false,
"_integrity": "sha512-WIiGp37XXDC6e7ku3LFoi7LCL/Gs9luGeeqvbPRb+Zl6OQMw4RCRfSaW+aLfE6lhz1R941UavE6Svl3Dm5xGIQ==",
"_location": "/@google-cloud/common/retry-request",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "retry-request@^3.0.0",
"name": "retry-request",
"escapedName": "retry-request",
"rawSpec": "^3.0.0",
"saveSpec": null,
"fetchSpec": "^3.0.0"
},
"_requiredBy": [
"/@google-cloud/common"
],
"_resolved": "https://registry.npmjs.org/retry-request/-/retry-request-3.3.2.tgz",
"_shasum": "fd8e0079e7b0dfc7056e500b6f089437db0da4df",
"_spec": "retry-request@^3.0.0",
"_where": "D:\\Desktop\\Git\\Firebase\\SmartShopperFirebase\\node_modules\\@google-cloud\\common",
"author": {
"name": "Stephen Sawchuk",
"email": "sawchuk@gmail.com"
},
"bugs": {
"url": "https://github.com/stephenplusplus/retry-request/issues"
},
"bundleDependencies": false,
"dependencies": {
"request": "^2.81.0",
"through2": "^2.0.0"
},
"deprecated": false,
"description": "Retry a request.",
"devDependencies": {
"async": "^2.5.0",
"lodash.range": "^3.2.0",
"mocha": "^2.2.5"
},
"engines": {
"node": ">=4"
},
"files": [
"index.js",
"index.d.ts",
"license"
],
"homepage": "https://github.com/stephenplusplus/retry-request#readme",
"keywords": [
"request",
"retry",
"stream"
],
"license": "MIT",
"main": "index.js",
"name": "retry-request",
"repository": {
"type": "git",
"url": "git+https://github.com/stephenplusplus/retry-request.git"
},
"scripts": {
"test": "mocha --timeout 0"
},
"types": "index.d.ts",
"version": "3.3.2"
}

View File

@ -0,0 +1,152 @@
|![retry-request](logo.png)
|:-:
|Retry a [request][request] with built-in [exponential backoff](https://developers.google.com/analytics/devguides/reporting/core/v3/coreErrors#backoff).
```sh
$ npm install --save retry-request
```
```js
var request = require('retry-request');
```
It should work the same as `request` in both callback mode and stream mode.
Note: This module only works when used as a readable stream, i.e. POST requests aren't supported ([#3](https://github.com/stephenplusplus/retry-request/issues/3)).
#### Callback
`urlThatReturns503` will be requested 3 total times before giving up and executing the callback.
```js
request(urlThatReturns503, function (err, resp, body) {});
```
#### Stream
`urlThatReturns503` will be requested 3 total times before giving up and emitting the `response` and `complete` event as usual.
```js
request(urlThatReturns503)
.on('error', function () {})
.on('response', function () {})
.on('complete', function () {});
```
## request(requestOptions, [opts], [cb])
### requestOptions
Passed directly to `request`. See the list of options supported: https://github.com/request/request/#requestoptions-callback.
### opts *(optional)*
#### `opts.noResponseRetries`
Type: `Number`
Default: `2`
The number of times to retry after a response fails to come through, such as a DNS resolution error or a socket hangup.
```js
var opts = {
noResponseRetries: 0
};
request(url, opts, function (err, resp, body) {
// url was requested 1 time before giving up and
// executing this callback.
});
```
#### `opts.objectMode`
Type: `Boolean`
Default: `false`
Set to `true` if your custom `opts.request` function returns a stream in object mode.
#### `opts.retries`
Type: `Number`
Default: `2`
```js
var opts = {
retries: 4
};
request(urlThatReturns503, opts, function (err, resp, body) {
// urlThatReturns503 was requested a total of 5 times
// before giving up and executing this callback.
});
```
#### `opts.currentRetryAttempt`
Type: `Number`
Default: `0`
```js
var opts = {
currentRetryAttempt: 1
};
request(urlThatReturns503, opts, function (err, resp, body) {
// urlThatReturns503 was requested as if it already failed once.
});
```
#### `opts.shouldRetryFn`
Type: `Function`
Default: Returns `true` if [http.incomingMessage](https://nodejs.org/api/http.html#http_http_incomingmessage).statusCode is < 200 or >= 400.
```js
var opts = {
shouldRetryFn: function (incomingHttpMessage) {
return incomingHttpMessage.statusMessage !== 'OK';
}
};
request(urlThatReturnsNonOKStatusMessage, opts, function (err, resp, body) {
// urlThatReturnsNonOKStatusMessage was requested a
// total of 3 times, each time using `opts.shouldRetryFn`
// to decide if it should continue before giving up and
// executing this callback.
});
```
#### `opts.request`
Type: `Function`
Default: [`request`][request]
*NOTE: If you override the request function, and it returns a stream in object mode, be sure to set `opts.objectMode` to `true`.*
```js
var originalRequest = require('request').defaults({
pool: {
maxSockets: Infinity
}
});
var opts = {
request: originalRequest
};
request(urlThatReturns503, opts, function (err, resp, body) {
// Your provided `originalRequest` instance was used.
});
```
### cb *(optional)*
Passed directly to `request`. See the callback section: https://github.com/request/request/#requestoptions-callback.
[request]: https://github.com/request/request

View File

@ -0,0 +1,50 @@
sudo: false
language: node_js
before_install:
- npm install -g npm@2
- test $NPM_LEGACY && npm install -g npm@latest-3 || npm install npm -g
notifications:
email: false
matrix:
fast_finish: true
include:
- node_js: '0.8'
env:
- TASK=test
- NPM_LEGACY=true
- node_js: '0.10'
env:
- TASK=test
- NPM_LEGACY=true
- node_js: '0.11'
env:
- TASK=test
- NPM_LEGACY=true
- node_js: '0.12'
env:
- TASK=test
- NPM_LEGACY=true
- node_js: 1
env:
- TASK=test
- NPM_LEGACY=true
- node_js: 2
env:
- TASK=test
- NPM_LEGACY=true
- node_js: 3
env:
- TASK=test
- NPM_LEGACY=true
- node_js: 4
env: TASK=test
- node_js: 5
env: TASK=test
- node_js: 6
env: TASK=test
- node_js: 7
env: TASK=test
- node_js: 8
env: TASK=test
- node_js: 9
env: TASK=test

View File

@ -0,0 +1,48 @@
Node.js is licensed for use as follows:
"""
Copyright Node.js contributors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
"""
This license applies to parts of Node.js originating from the
https://github.com/joyent/node repository:
"""
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
"""

View File

@ -0,0 +1,47 @@
# string_decoder
***Node-core v8.9.4 string_decoder for userland***
[![NPM](https://nodei.co/npm/string_decoder.png?downloads=true&downloadRank=true)](https://nodei.co/npm/string_decoder/)
[![NPM](https://nodei.co/npm-dl/string_decoder.png?&months=6&height=3)](https://nodei.co/npm/string_decoder/)
```bash
npm install --save string_decoder
```
***Node-core string_decoder for userland***
This package is a mirror of the string_decoder implementation in Node-core.
Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v8.9.4/docs/api/).
As of version 1.0.0 **string_decoder** uses semantic versioning.
## Previous versions
Previous version numbers match the versions found in Node core, e.g. 0.10.24 matches Node 0.10.24, likewise 0.11.10 matches Node 0.11.10.
## Update
The *build/* directory contains a build script that will scrape the source from the [nodejs/node](https://github.com/nodejs/node) repo given a specific Node version.
## Streams Working Group
`string_decoder` is maintained by the Streams Working Group, which
oversees the development and maintenance of the Streams API within
Node.js. The responsibilities of the Streams Working Group include:
* Addressing stream issues on the Node.js issue tracker.
* Authoring and editing stream documentation within the Node.js project.
* Reviewing changes to stream subclasses within the Node.js project.
* Redirecting changes to streams from the Node.js project to this
project.
* Assisting in the implementation of stream providers within Node.js.
* Recommending versions of `readable-stream` to be included in Node.js.
* Messaging about the future of streams to give the community advance
notice of changes.
See [readable-stream](https://github.com/nodejs/readable-stream) for
more details.

View File

@ -0,0 +1,296 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict';
/*<replacement>*/
var Buffer = require('safe-buffer').Buffer;
/*</replacement>*/
var isEncoding = Buffer.isEncoding || function (encoding) {
encoding = '' + encoding;
switch (encoding && encoding.toLowerCase()) {
case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw':
return true;
default:
return false;
}
};
function _normalizeEncoding(enc) {
if (!enc) return 'utf8';
var retried;
while (true) {
switch (enc) {
case 'utf8':
case 'utf-8':
return 'utf8';
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return 'utf16le';
case 'latin1':
case 'binary':
return 'latin1';
case 'base64':
case 'ascii':
case 'hex':
return enc;
default:
if (retried) return; // undefined
enc = ('' + enc).toLowerCase();
retried = true;
}
}
};
// Do not cache `Buffer.isEncoding` when checking encoding names as some
// modules monkey-patch it to support additional encodings
function normalizeEncoding(enc) {
var nenc = _normalizeEncoding(enc);
if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc);
return nenc || enc;
}
// StringDecoder provides an interface for efficiently splitting a series of
// buffers into a series of JS strings without breaking apart multi-byte
// characters.
exports.StringDecoder = StringDecoder;
function StringDecoder(encoding) {
this.encoding = normalizeEncoding(encoding);
var nb;
switch (this.encoding) {
case 'utf16le':
this.text = utf16Text;
this.end = utf16End;
nb = 4;
break;
case 'utf8':
this.fillLast = utf8FillLast;
nb = 4;
break;
case 'base64':
this.text = base64Text;
this.end = base64End;
nb = 3;
break;
default:
this.write = simpleWrite;
this.end = simpleEnd;
return;
}
this.lastNeed = 0;
this.lastTotal = 0;
this.lastChar = Buffer.allocUnsafe(nb);
}
StringDecoder.prototype.write = function (buf) {
if (buf.length === 0) return '';
var r;
var i;
if (this.lastNeed) {
r = this.fillLast(buf);
if (r === undefined) return '';
i = this.lastNeed;
this.lastNeed = 0;
} else {
i = 0;
}
if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i);
return r || '';
};
StringDecoder.prototype.end = utf8End;
// Returns only complete characters in a Buffer
StringDecoder.prototype.text = utf8Text;
// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer
StringDecoder.prototype.fillLast = function (buf) {
if (this.lastNeed <= buf.length) {
buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed);
return this.lastChar.toString(this.encoding, 0, this.lastTotal);
}
buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length);
this.lastNeed -= buf.length;
};
// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a
// continuation byte. If an invalid byte is detected, -2 is returned.
function utf8CheckByte(byte) {
if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4;
return byte >> 6 === 0x02 ? -1 : -2;
}
// Checks at most 3 bytes at the end of a Buffer in order to detect an
// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4)
// needed to complete the UTF-8 character (if applicable) are returned.
function utf8CheckIncomplete(self, buf, i) {
var j = buf.length - 1;
if (j < i) return 0;
var nb = utf8CheckByte(buf[j]);
if (nb >= 0) {
if (nb > 0) self.lastNeed = nb - 1;
return nb;
}
if (--j < i || nb === -2) return 0;
nb = utf8CheckByte(buf[j]);
if (nb >= 0) {
if (nb > 0) self.lastNeed = nb - 2;
return nb;
}
if (--j < i || nb === -2) return 0;
nb = utf8CheckByte(buf[j]);
if (nb >= 0) {
if (nb > 0) {
if (nb === 2) nb = 0;else self.lastNeed = nb - 3;
}
return nb;
}
return 0;
}
// Validates as many continuation bytes for a multi-byte UTF-8 character as
// needed or are available. If we see a non-continuation byte where we expect
// one, we "replace" the validated continuation bytes we've seen so far with
// a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding
// behavior. The continuation byte check is included three times in the case
// where all of the continuation bytes for a character exist in the same buffer.
// It is also done this way as a slight performance increase instead of using a
// loop.
function utf8CheckExtraBytes(self, buf, p) {
if ((buf[0] & 0xC0) !== 0x80) {
self.lastNeed = 0;
return '\ufffd';
}
if (self.lastNeed > 1 && buf.length > 1) {
if ((buf[1] & 0xC0) !== 0x80) {
self.lastNeed = 1;
return '\ufffd';
}
if (self.lastNeed > 2 && buf.length > 2) {
if ((buf[2] & 0xC0) !== 0x80) {
self.lastNeed = 2;
return '\ufffd';
}
}
}
}
// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer.
function utf8FillLast(buf) {
var p = this.lastTotal - this.lastNeed;
var r = utf8CheckExtraBytes(this, buf, p);
if (r !== undefined) return r;
if (this.lastNeed <= buf.length) {
buf.copy(this.lastChar, p, 0, this.lastNeed);
return this.lastChar.toString(this.encoding, 0, this.lastTotal);
}
buf.copy(this.lastChar, p, 0, buf.length);
this.lastNeed -= buf.length;
}
// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a
// partial character, the character's bytes are buffered until the required
// number of bytes are available.
function utf8Text(buf, i) {
var total = utf8CheckIncomplete(this, buf, i);
if (!this.lastNeed) return buf.toString('utf8', i);
this.lastTotal = total;
var end = buf.length - (total - this.lastNeed);
buf.copy(this.lastChar, 0, end);
return buf.toString('utf8', i, end);
}
// For UTF-8, a replacement character is added when ending on a partial
// character.
function utf8End(buf) {
var r = buf && buf.length ? this.write(buf) : '';
if (this.lastNeed) return r + '\ufffd';
return r;
}
// UTF-16LE typically needs two bytes per character, but even if we have an even
// number of bytes available, we need to check if we end on a leading/high
// surrogate. In that case, we need to wait for the next two bytes in order to
// decode the last character properly.
function utf16Text(buf, i) {
if ((buf.length - i) % 2 === 0) {
var r = buf.toString('utf16le', i);
if (r) {
var c = r.charCodeAt(r.length - 1);
if (c >= 0xD800 && c <= 0xDBFF) {
this.lastNeed = 2;
this.lastTotal = 4;
this.lastChar[0] = buf[buf.length - 2];
this.lastChar[1] = buf[buf.length - 1];
return r.slice(0, -1);
}
}
return r;
}
this.lastNeed = 1;
this.lastTotal = 2;
this.lastChar[0] = buf[buf.length - 1];
return buf.toString('utf16le', i, buf.length - 1);
}
// For UTF-16LE we do not explicitly append special replacement characters if we
// end on a partial character, we simply let v8 handle that.
function utf16End(buf) {
var r = buf && buf.length ? this.write(buf) : '';
if (this.lastNeed) {
var end = this.lastTotal - this.lastNeed;
return r + this.lastChar.toString('utf16le', 0, end);
}
return r;
}
function base64Text(buf, i) {
var n = (buf.length - i) % 3;
if (n === 0) return buf.toString('base64', i);
this.lastNeed = 3 - n;
this.lastTotal = 3;
if (n === 1) {
this.lastChar[0] = buf[buf.length - 1];
} else {
this.lastChar[0] = buf[buf.length - 2];
this.lastChar[1] = buf[buf.length - 1];
}
return buf.toString('base64', i, buf.length - n);
}
function base64End(buf) {
var r = buf && buf.length ? this.write(buf) : '';
if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed);
return r;
}
// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex)
function simpleWrite(buf) {
return buf.toString(this.encoding);
}
function simpleEnd(buf) {
return buf && buf.length ? this.write(buf) : '';
}

View File

@ -0,0 +1,59 @@
{
"_from": "string_decoder@~1.1.1",
"_id": "string_decoder@1.1.1",
"_inBundle": false,
"_integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"_location": "/@google-cloud/common/string_decoder",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "string_decoder@~1.1.1",
"name": "string_decoder",
"escapedName": "string_decoder",
"rawSpec": "~1.1.1",
"saveSpec": null,
"fetchSpec": "~1.1.1"
},
"_requiredBy": [
"/@google-cloud/common/readable-stream"
],
"_resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"_shasum": "9cf1611ba62685d7030ae9e4ba34149c3af03fc8",
"_spec": "string_decoder@~1.1.1",
"_where": "D:\\Desktop\\Git\\Firebase\\SmartShopperFirebase\\node_modules\\@google-cloud\\common\\node_modules\\readable-stream",
"bugs": {
"url": "https://github.com/nodejs/string_decoder/issues"
},
"bundleDependencies": false,
"dependencies": {
"safe-buffer": "~5.1.0"
},
"deprecated": false,
"description": "The string_decoder module from Node core",
"devDependencies": {
"babel-polyfill": "^6.23.0",
"core-util-is": "^1.0.2",
"inherits": "^2.0.3",
"tap": "~0.4.8"
},
"homepage": "https://github.com/nodejs/string_decoder",
"keywords": [
"string",
"decoder",
"browser",
"browserify"
],
"license": "MIT",
"main": "lib/string_decoder.js",
"name": "string_decoder",
"repository": {
"type": "git",
"url": "git://github.com/nodejs/string_decoder.git"
},
"scripts": {
"ci": "tap test/parallel/*.js test/ours/*.js --tap | tee test.tap && node test/verify-dependencies.js",
"test": "tap test/parallel/*.js && node test/verify-dependencies"
},
"version": "1.1.1"
}

View File

@ -0,0 +1,9 @@
# The MIT License (MIT)
**Copyright (c) Rod Vagg (the "Original Author") and additional contributors**
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,134 @@
# through2
[![NPM](https://nodei.co/npm/through2.png?downloads&downloadRank)](https://nodei.co/npm/through2/)
**A tiny wrapper around Node streams.Transform (Streams2/3) to avoid explicit subclassing noise**
Inspired by [Dominic Tarr](https://github.com/dominictarr)'s [through](https://github.com/dominictarr/through) in that it's so much easier to make a stream out of a function than it is to set up the prototype chain properly: `through(function (chunk) { ... })`.
Note: As 2.x.x this module starts using **Streams3** instead of Stream2. To continue using a Streams2 version use `npm install through2@0` to fetch the latest version of 0.x.x. More information about Streams2 vs Streams3 and recommendations see the article **[Why I don't use Node's core 'stream' module](http://r.va.gg/2014/06/why-i-dont-use-nodes-core-stream-module.html)**.
```js
fs.createReadStream('ex.txt')
.pipe(through2(function (chunk, enc, callback) {
for (var i = 0; i < chunk.length; i++)
if (chunk[i] == 97)
chunk[i] = 122 // swap 'a' for 'z'
this.push(chunk)
callback()
}))
.pipe(fs.createWriteStream('out.txt'))
.on('finish', () => doSomethingSpecial())
```
Or object streams:
```js
var all = []
fs.createReadStream('data.csv')
.pipe(csv2())
.pipe(through2.obj(function (chunk, enc, callback) {
var data = {
name : chunk[0]
, address : chunk[3]
, phone : chunk[10]
}
this.push(data)
callback()
}))
.on('data', (data) => {
all.push(data)
})
.on('end', () => {
doSomethingSpecial(all)
})
```
Note that `through2.obj(fn)` is a convenience wrapper around `through2({ objectMode: true }, fn)`.
## API
<b><code>through2([ options, ] [ transformFunction ] [, flushFunction ])</code></b>
Consult the **[stream.Transform](http://nodejs.org/docs/latest/api/stream.html#stream_class_stream_transform)** documentation for the exact rules of the `transformFunction` (i.e. `this._transform`) and the optional `flushFunction` (i.e. `this._flush`).
### options
The options argument is optional and is passed straight through to `stream.Transform`. So you can use `objectMode:true` if you are processing non-binary streams (or just use `through2.obj()`).
The `options` argument is first, unlike standard convention, because if I'm passing in an anonymous function then I'd prefer for the options argument to not get lost at the end of the call:
```js
fs.createReadStream('/tmp/important.dat')
.pipe(through2({ objectMode: true, allowHalfOpen: false },
(chunk, enc, cb) => {
cb(null, 'wut?') // note we can use the second argument on the callback
// to provide data as an alternative to this.push('wut?')
}
)
.pipe(fs.createWriteStream('/tmp/wut.txt'))
```
### transformFunction
The `transformFunction` must have the following signature: `function (chunk, encoding, callback) {}`. A minimal implementation should call the `callback` function to indicate that the transformation is done, even if that transformation means discarding the chunk.
To queue a new chunk, call `this.push(chunk)`&mdash;this can be called as many times as required before the `callback()` if you have multiple pieces to send on.
Alternatively, you may use `callback(err, chunk)` as shorthand for emitting a single chunk or an error.
If you **do not provide a `transformFunction`** then you will get a simple pass-through stream.
### flushFunction
The optional `flushFunction` is provided as the last argument (2nd or 3rd, depending on whether you've supplied options) is called just prior to the stream ending. Can be used to finish up any processing that may be in progress.
```js
fs.createReadStream('/tmp/important.dat')
.pipe(through2(
(chunk, enc, cb) => cb(null, chunk), // transform is a noop
function (cb) { // flush function
this.push('tacking on an extra buffer to the end');
cb();
}
))
.pipe(fs.createWriteStream('/tmp/wut.txt'));
```
<b><code>through2.ctor([ options, ] transformFunction[, flushFunction ])</code></b>
Instead of returning a `stream.Transform` instance, `through2.ctor()` returns a **constructor** for a custom Transform. This is useful when you want to use the same transform logic in multiple instances.
```js
var FToC = through2.ctor({objectMode: true}, function (record, encoding, callback) {
if (record.temp != null && record.unit == "F") {
record.temp = ( ( record.temp - 32 ) * 5 ) / 9
record.unit = "C"
}
this.push(record)
callback()
})
// Create instances of FToC like so:
var converter = new FToC()
// Or:
var converter = FToC()
// Or specify/override options when you instantiate, if you prefer:
var converter = FToC({objectMode: true})
```
## See Also
- [through2-map](https://github.com/brycebaril/through2-map) - Array.prototype.map analog for streams.
- [through2-filter](https://github.com/brycebaril/through2-filter) - Array.prototype.filter analog for streams.
- [through2-reduce](https://github.com/brycebaril/through2-reduce) - Array.prototype.reduce analog for streams.
- [through2-spy](https://github.com/brycebaril/through2-spy) - Wrapper for simple stream.PassThrough spies.
- the [mississippi stream utility collection](https://github.com/maxogden/mississippi) includes `through2` as well as many more useful stream modules similar to this one
## License
**through2** is Copyright (c) Rod Vagg [@rvagg](https://twitter.com/rvagg) and additional contributors and licensed under the MIT license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.

View File

@ -0,0 +1,67 @@
{
"_from": "through2@^2.0.3",
"_id": "through2@2.0.5",
"_inBundle": false,
"_integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"_location": "/@google-cloud/common/through2",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "through2@^2.0.3",
"name": "through2",
"escapedName": "through2",
"rawSpec": "^2.0.3",
"saveSpec": null,
"fetchSpec": "^2.0.3"
},
"_requiredBy": [
"/@google-cloud/common",
"/@google-cloud/common/retry-request"
],
"_resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"_shasum": "01c1e39eb31d07cb7d03a96a70823260b23132cd",
"_spec": "through2@^2.0.3",
"_where": "D:\\Desktop\\Git\\Firebase\\SmartShopperFirebase\\node_modules\\@google-cloud\\common",
"author": {
"name": "Rod Vagg",
"email": "r@va.gg",
"url": "https://github.com/rvagg"
},
"bugs": {
"url": "https://github.com/rvagg/through2/issues"
},
"bundleDependencies": false,
"dependencies": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
},
"deprecated": false,
"description": "A tiny wrapper around Node streams2 Transform to avoid explicit subclassing noise",
"devDependencies": {
"bl": "~2.0.1",
"faucet": "0.0.1",
"nyc": "~13.1.0",
"safe-buffer": "~5.1.2",
"stream-spigot": "~3.0.6",
"tape": "~4.9.1"
},
"homepage": "https://github.com/rvagg/through2#readme",
"keywords": [
"stream",
"streams2",
"through",
"transform"
],
"license": "MIT",
"main": "through2.js",
"name": "through2",
"repository": {
"type": "git",
"url": "git+https://github.com/rvagg/through2.git"
},
"scripts": {
"test": "node test/test.js | faucet"
},
"version": "2.0.5"
}

View File

@ -0,0 +1,96 @@
var Transform = require('readable-stream').Transform
, inherits = require('util').inherits
, xtend = require('xtend')
function DestroyableTransform(opts) {
Transform.call(this, opts)
this._destroyed = false
}
inherits(DestroyableTransform, Transform)
DestroyableTransform.prototype.destroy = function(err) {
if (this._destroyed) return
this._destroyed = true
var self = this
process.nextTick(function() {
if (err)
self.emit('error', err)
self.emit('close')
})
}
// a noop _transform function
function noop (chunk, enc, callback) {
callback(null, chunk)
}
// create a new export function, used by both the main export and
// the .ctor export, contains common logic for dealing with arguments
function through2 (construct) {
return function (options, transform, flush) {
if (typeof options == 'function') {
flush = transform
transform = options
options = {}
}
if (typeof transform != 'function')
transform = noop
if (typeof flush != 'function')
flush = null
return construct(options, transform, flush)
}
}
// main export, just make me a transform stream!
module.exports = through2(function (options, transform, flush) {
var t2 = new DestroyableTransform(options)
t2._transform = transform
if (flush)
t2._flush = flush
return t2
})
// make me a reusable prototype that I can `new`, or implicitly `new`
// with a constructor call
module.exports.ctor = through2(function (options, transform, flush) {
function Through2 (override) {
if (!(this instanceof Through2))
return new Through2(override)
this.options = xtend(options, override)
DestroyableTransform.call(this, this.options)
}
inherits(Through2, DestroyableTransform)
Through2.prototype._transform = transform
if (flush)
Through2.prototype._flush = flush
return Through2
})
module.exports.obj = through2(function (options, transform, flush) {
var t2 = new DestroyableTransform(xtend({ objectMode: true, highWaterMark: 16 }, options))
t2._transform = transform
if (flush)
t2._flush = flush
return t2
})

View File

@ -0,0 +1,171 @@
{
"_from": "@google-cloud/common@^0.17.0",
"_id": "@google-cloud/common@0.17.0",
"_inBundle": false,
"_integrity": "sha512-HRZLSU762E6HaKoGfJGa8W95yRjb9rY7LePhjaHK9ILAnFacMuUGVamDbTHu1csZomm1g3tZTtXfX/aAhtie/Q==",
"_location": "/@google-cloud/common",
"_phantomChildren": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"process-nextick-args": "2.0.0",
"request": "2.88.0",
"safe-buffer": "5.1.2",
"util-deprecate": "1.0.2",
"xtend": "4.0.1"
},
"_requested": {
"type": "range",
"registry": true,
"raw": "@google-cloud/common@^0.17.0",
"name": "@google-cloud/common",
"escapedName": "@google-cloud%2fcommon",
"scope": "@google-cloud",
"rawSpec": "^0.17.0",
"saveSpec": null,
"fetchSpec": "^0.17.0"
},
"_requiredBy": [
"/@google-cloud/storage"
],
"_resolved": "http://registry.npmjs.org/@google-cloud/common/-/common-0.17.0.tgz",
"_shasum": "8ef558750db481fc10a13757a49479ab9a1c8c07",
"_spec": "@google-cloud/common@^0.17.0",
"_where": "D:\\Desktop\\Git\\Firebase\\SmartShopperFirebase\\node_modules\\@google-cloud\\storage",
"author": {
"name": "Google Inc."
},
"bugs": {
"url": "https://github.com/googleapis/nodejs-common/issues"
},
"bundleDependencies": false,
"contributors": [
{
"name": "Ali Ijaz Sheikh",
"email": "ofrobots@google.com"
},
{
"name": "Austin Peterson",
"email": "austin@akpwebdesign.com"
},
{
"name": "Dave Gramlich",
"email": "callmehiphop@gmail.com"
},
{
"name": "Eric Uldall",
"email": "ericuldall@gmail.com"
},
{
"name": "Ernest Landrito",
"email": "landrito@google.com"
},
{
"name": "Jason Dobry",
"email": "jdobry@google.com"
},
{
"name": "Justin King",
"email": "jcking@mtu.edu"
},
{
"name": "Karolis Narkevicius",
"email": "karolis.n@gmail.com"
},
{
"name": "Kelvin Jin",
"email": "kelvinjin@google.com"
},
{
"name": "Luke Sneeringer",
"email": "lukesneeringer@google.com"
},
{
"name": "Matthew Loring",
"email": "matthewloring@users.noreply.github.com"
},
{
"name": "Michael Prentice",
"email": "splaktar@gmail.com"
},
{
"name": "Stephen Sawchuk",
"email": "sawchuk@gmail.com"
},
{
"name": "Tim Swast",
"email": "swast@google.com"
}
],
"dependencies": {
"array-uniq": "^1.0.3",
"arrify": "^1.0.1",
"concat-stream": "^1.6.0",
"create-error-class": "^3.0.2",
"duplexify": "^3.5.0",
"ent": "^2.2.0",
"extend": "^3.0.1",
"google-auto-auth": "^0.10.0",
"is": "^3.2.0",
"log-driver": "1.2.7",
"methmeth": "^1.1.0",
"modelo": "^4.2.0",
"request": "^2.79.0",
"retry-request": "^3.0.0",
"split-array-stream": "^1.0.0",
"stream-events": "^1.0.1",
"string-format-obj": "^1.1.0",
"through2": "^2.0.3"
},
"deprecated": false,
"description": "Common components for Cloud APIs Node.js Client Libraries",
"devDependencies": {
"@google-cloud/nodejs-repo-tools": "^2.1.1",
"async": "^2.6.0",
"codecov": "^3.0.0",
"eslint": "^4.10.0",
"eslint-config-prettier": "^2.7.0",
"eslint-plugin-node": "^6.0.0",
"eslint-plugin-prettier": "^2.3.1",
"ink-docstrap": "^1.3.0",
"intelli-espower-loader": "^1.0.1",
"js-green-licenses": "^0.5.0",
"jsdoc": "^3.5.5",
"mocha": "^5.0.0",
"nyc": "^11.3.0",
"power-assert": "^1.4.4",
"prettier": "^1.11.1",
"proxyquire": "^2.0.0",
"uuid": "^3.0.1"
},
"engines": {
"node": ">=4.0.0"
},
"files": [
"src",
"AUTHORS",
"CONTRIBUTORS",
"LICENSE"
],
"homepage": "https://github.com/googleapis/nodejs-common#readme",
"license": "Apache-2.0",
"main": "./src/index.js",
"name": "@google-cloud/common",
"repository": {
"type": "git",
"url": "git+https://github.com/googleapis/nodejs-common.git"
},
"scripts": {
"cover": "nyc --reporter=lcov mocha --require intelli-espower-loader test/*.js && nyc report",
"docs": "repo-tools exec -- jsdoc -c .jsdoc.js",
"generate-scaffolding": "repo-tools generate all",
"license-check": "jsgl --local .",
"lint": "repo-tools lint --cmd eslint -- src/ samples/ system-test/ test/",
"posttest": "npm run license-check",
"prettier": "repo-tools exec -- prettier --write src/*.js src/*/*.js samples/*.js samples/*/*.js test/*.js test/*/*.js system-test/*.js system-test/*/*.js",
"publish-module": "node ../../scripts/publish.js common",
"samples-test": "cd samples/ && npm link ../ && npm test && cd ../",
"test": "repo-tools test run --cmd npm -- run cover",
"test-no-cover": "repo-tools test run --cmd mocha -- test/*.js --no-timeouts"
},
"version": "0.17.0"
}

View File

@ -0,0 +1,51 @@
/*!
* 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.
*/
/**
* @type {module:common/logger}
* @private
*/
exports.logger = require('./logger.js');
/**
* @type {module:common/operation}
* @private
*/
exports.Operation = require('./operation.js');
/**
* @type {module:common/paginator}
* @private
*/
exports.paginator = require('./paginator.js');
/**
* @type {module:common/service}
* @private
*/
exports.Service = require('./service.js');
/**
* @type {module:common/serviceObject}
* @private
*/
exports.ServiceObject = require('./service-object.js');
/**
* @type {module:common/util}
* @private
*/
exports.util = require('./util.js');

View File

@ -0,0 +1,71 @@
/*!
* 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.
*/
'use strict';
/*!
* @module common/logger
*/
const format = require('string-format-obj');
const is = require('is');
const logDriver = require('log-driver');
/**
* The default list of log levels.
* @type {string[]}
*/
const LEVELS = ['silent', 'error', 'warn', 'info', 'debug', 'silly'];
/**
* Create a logger to print output to the console.
*
* @param {string=|object=} options - Configuration object. If a string, it is
* treated as `options.level`.
* @param {string=} options.level - The minimum log level that will print to the
* console. (Default: `error`)
* @param {Array.<string>=} options.levels - The list of levels to use. (Default:
* logger.LEVELS)
* @param {string=} options.tag - A tag to use in log messages.
*/
function logger(options) {
if (is.string(options)) {
options = {
level: options,
};
}
options = options || {};
return logDriver({
levels: options.levels || LEVELS,
level: options.level || 'error',
format: function() {
const args = [].slice.call(arguments);
return format('{level}{tag} {message}', {
level: args.shift().toUpperCase(),
tag: options.tag ? ':' + options.tag + ':' : '',
message: args.join(' '),
});
},
});
}
module.exports = logger;
module.exports.LEVELS = LEVELS;

View File

@ -0,0 +1,193 @@
/*!
* 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.
*/
/*!
* @module common/operation
*/
'use strict';
const events = require('events');
const extend = require('extend');
const modelo = require('modelo');
/**
* @type {module:common/serviceObject}
* @private
*/
const ServiceObject = require('./service-object.js');
// jscs:disable maximumLineLength
/**
* An Operation object allows you to interact with APIs that take longer to
* process things.
*
* @constructor
* @alias module:common/operation
*
* @param {object} config - Configuration object.
* @param {module:common/service|module:common/serviceObject|module:common/grpcService|module:common/grpcServiceObject} config.parent - The
* parent object.
* @param {string} id - The operation ID.
*/
// jscs:enable maximumLineLength
function Operation(config) {
const methods = {
/**
* Checks to see if an operation exists.
*/
exists: true,
/**
* Retrieves the operation.
*/
get: true,
/**
* Retrieves metadata for the operation.
*/
getMetadata: {
reqOpts: {
name: config.id,
},
},
};
config = extend(
{
baseUrl: '',
},
config
);
config.methods = config.methods || methods;
ServiceObject.call(this, config);
events.EventEmitter.call(this);
this.completeListeners = 0;
this.hasActiveListeners = false;
this.listenForEvents_();
}
modelo.inherits(Operation, ServiceObject, events.EventEmitter);
/**
* Wraps the `complete` and `error` events in a Promise.
*
* @return {promise}
*/
Operation.prototype.promise = function() {
const self = this;
return new self.Promise(function(resolve, reject) {
self.on('error', reject).on('complete', function(metadata) {
resolve([metadata]);
});
});
};
/**
* Begin listening for events on the operation. This method keeps track of how
* many "complete" listeners are registered and removed, making sure polling is
* handled automatically.
*
* As long as there is one active "complete" listener, the connection is open.
* When there are no more listeners, the polling stops.
*
* @private
*/
Operation.prototype.listenForEvents_ = function() {
const self = this;
this.on('newListener', function(event) {
if (event === 'complete') {
self.completeListeners++;
if (!self.hasActiveListeners) {
self.hasActiveListeners = true;
self.startPolling_();
}
}
});
this.on('removeListener', function(event) {
if (event === 'complete' && --self.completeListeners === 0) {
self.hasActiveListeners = false;
}
});
};
/**
* Poll for a status update. Execute the callback:
*
* - callback(err): Operation failed
* - callback(): Operation incomplete
* - callback(null, metadata): Operation complete
*
* @private
*
* @param {function} callback
*/
Operation.prototype.poll_ = function(callback) {
this.getMetadata(function(err, resp) {
if (err || resp.error) {
callback(err || resp.error);
return;
}
if (!resp.done) {
callback();
return;
}
callback(null, resp);
});
};
/**
* Poll `getMetadata` to check the operation's status. This runs a loop to ping
* the API on an interval.
*
* Note: This method is automatically called once a "complete" event handler is
* registered on the operation.
*
* @private
*/
Operation.prototype.startPolling_ = function() {
const self = this;
if (!this.hasActiveListeners) {
return;
}
this.poll_(function(err, metadata) {
if (err) {
self.emit('error', err);
return;
}
if (!metadata) {
setTimeout(self.startPolling_.bind(self), 500);
return;
}
self.emit('complete', metadata);
});
};
module.exports = Operation;

View File

@ -0,0 +1,267 @@
/*!
* Copyright 2015 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.
*/
/*!
* @module common/paginator
*/
'use strict';
const arrify = require('arrify');
const concat = require('concat-stream');
const extend = require('extend');
const is = require('is');
const split = require('split-array-stream');
/**
* @type {module:common/util}
* @private
*/
const util = require('./util.js');
/*! Developer Documentation
*
* paginator is used to auto-paginate `nextQuery` methods as well as
* streamifying them.
*
* Before:
*
* search.query('done=true', function(err, results, nextQuery) {
* search.query(nextQuery, function(err, results, nextQuery) {});
* });
*
* After:
*
* search.query('done=true', function(err, results) {});
*
* Methods to extend should be written to accept callbacks and return a
* `nextQuery`.
*/
const paginator = {};
/**
* Cache the original method, then overwrite it on the Class's prototype.
*
* @param {function} Class - The parent class of the methods to extend.
* @param {string|string[]} methodNames - Name(s) of the methods to extend.
*/
paginator.extend = function(Class, methodNames) {
methodNames = arrify(methodNames);
methodNames.forEach(function(methodName) {
const originalMethod = Class.prototype[methodName];
// map the original method to a private member
Class.prototype[methodName + '_'] = originalMethod;
// overwrite the original to auto-paginate
Class.prototype[methodName] = function() {
const parsedArguments = paginator.parseArguments_(arguments);
return paginator.run_(parsedArguments, originalMethod.bind(this));
};
});
};
/**
* Wraps paginated API calls in a readable object stream.
*
* This method simply calls the nextQuery recursively, emitting results to a
* stream. The stream ends when `nextQuery` is null.
*
* `maxResults` will act as a cap for how many results are fetched and emitted
* to the stream.
*
* @param {string} methodName - Name of the method to streamify.
* @return {function} - Wrapped function.
*/
paginator.streamify = function(methodName) {
return function() {
const parsedArguments = paginator.parseArguments_(arguments);
const originalMethod = this[methodName + '_'] || this[methodName];
return paginator.runAsStream_(parsedArguments, originalMethod.bind(this));
};
};
/**
* Parse a pseudo-array `arguments` for a query and callback.
*
* @param {array} args - The original `arguments` pseduo-array that the original
* method received.
*/
paginator.parseArguments_ = function(args) {
let query;
let autoPaginate = true;
let maxApiCalls = -1;
let maxResults = -1;
let callback;
const firstArgument = args[0];
const lastArgument = args[args.length - 1];
if (is.fn(firstArgument)) {
callback = firstArgument;
} else {
query = firstArgument;
}
if (is.fn(lastArgument)) {
callback = lastArgument;
}
if (is.object(query)) {
query = extend(true, {}, query);
// Check if the user only asked for a certain amount of results.
if (is.number(query.maxResults)) {
// `maxResults` is used API-wide.
maxResults = query.maxResults;
} else if (is.number(query.pageSize)) {
// `pageSize` is Pub/Sub's `maxResults`.
maxResults = query.pageSize;
}
if (is.number(query.maxApiCalls)) {
maxApiCalls = query.maxApiCalls;
delete query.maxApiCalls;
}
if (
callback &&
(maxResults !== -1 || // The user specified a limit.
query.autoPaginate === false)
) {
autoPaginate = false;
}
}
const parsedArguments = {
query: query || {},
autoPaginate: autoPaginate,
maxApiCalls: maxApiCalls,
maxResults: maxResults,
callback: callback,
};
parsedArguments.streamOptions = extend(true, {}, parsedArguments.query);
delete parsedArguments.streamOptions.autoPaginate;
delete parsedArguments.streamOptions.maxResults;
delete parsedArguments.streamOptions.pageSize;
return parsedArguments;
};
/**
* This simply checks to see if `autoPaginate` is set or not, if it's true
* then we buffer all results, otherwise simply call the original method.
*
* @param {array} parsedArguments - Parsed arguments from the original method
* call.
* @param {object=|string=} parsedArguments.query - Query object. This is most
* commonly an object, but to make the API more simple, it can also be a
* string in some places.
* @param {function=} parsedArguments.callback - Callback function.
* @param {boolean} parsedArguments.autoPaginate - Auto-pagination enabled.
* @param {boolean} parsedArguments.maxApiCalls - Maximum API calls to make.
* @param {number} parsedArguments.maxResults - Maximum results to return.
* @param {function} originalMethod - The cached method that accepts a callback
* and returns `nextQuery` to receive more results.
*/
paginator.run_ = function(parsedArguments, originalMethod) {
const query = parsedArguments.query;
const callback = parsedArguments.callback;
const autoPaginate = parsedArguments.autoPaginate;
if (autoPaginate) {
this.runAsStream_(parsedArguments, originalMethod)
.on('error', callback)
.pipe(
concat(function(results) {
callback(null, results);
})
);
} else {
originalMethod(query, callback);
}
};
/**
* This method simply calls the nextQuery recursively, emitting results to a
* stream. The stream ends when `nextQuery` is null.
*
* `maxResults` will act as a cap for how many results are fetched and emitted
* to the stream.
*
* @param {object=|string=} parsedArguments.query - Query object. This is most
* commonly an object, but to make the API more simple, it can also be a
* string in some places.
* @param {function=} parsedArguments.callback - Callback function.
* @param {boolean} parsedArguments.autoPaginate - Auto-pagination enabled.
* @param {boolean} parsedArguments.maxApiCalls - Maximum API calls to make.
* @param {number} parsedArguments.maxResults - Maximum results to return.
* @param {function} originalMethod - The cached method that accepts a callback
* and returns `nextQuery` to receive more results.
* @return {stream} - Readable object stream.
*/
paginator.runAsStream_ = function(parsedArguments, originalMethod) {
let query = parsedArguments.query;
let resultsToSend = parsedArguments.maxResults;
const limiter = util.createLimiter(makeRequest, {
maxApiCalls: parsedArguments.maxApiCalls,
streamOptions: parsedArguments.streamOptions,
});
const stream = limiter.stream;
stream.once('reading', function() {
makeRequest(query);
});
function makeRequest(query) {
originalMethod(query, onResultSet);
}
function onResultSet(err, results, nextQuery) {
if (err) {
stream.destroy(err);
return;
}
if (resultsToSend >= 0 && results.length > resultsToSend) {
results = results.splice(0, resultsToSend);
}
resultsToSend -= results.length;
split(results, stream, function(streamEnded) {
if (streamEnded) {
return;
}
if (nextQuery && resultsToSend !== 0) {
limiter.makeRequest(nextQuery);
return;
}
stream.push(null);
});
}
return limiter.stream;
};
module.exports = paginator;

View File

@ -0,0 +1,392 @@
/*!
* Copyright 2015 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.
*/
/*!
* @module common/service-object
*/
'use strict';
const arrify = require('arrify');
const exec = require('methmeth');
const extend = require('extend');
const is = require('is');
/**
* @type {module:common/util}
* @private
*/
const util = require('./util.js');
/**
* ServiceObject is a base class, meant to be inherited from by a "service
* object," like a BigQuery dataset or Storage bucket.
*
* Most of the time, these objects share common functionality; they can be
* created or deleted, and you can get or set their metadata.
*
* By inheriting from this class, a service object will be extended with these
* shared behaviors. Note that any method can be overridden when the service
* object requires specific behavior.
*
* @constructor
* @alias module:common/service-object
*
* @private
*
* @param {object} config - Configuration object.
* @param {string} config.baseUrl - The base URL to make API requests to.
* @param {string} config.createMethod - The method which creates this object.
* @param {string=} config.id - The identifier of the object. For example, the
* name of a Storage bucket or Pub/Sub topic.
* @param {object=} config.methods - A map of each method name that should be
* inherited.
* @param {object} config.methods[].reqOpts - Default request options for this
* particular method. A common use case is when `setMetadata` requires a
* `PUT` method to override the default `PATCH`.
* @param {object} config.parent - The parent service instance. For example, an
* instance of Storage if the object is Bucket.
*/
function ServiceObject(config) {
const self = this;
util.privatize(this, 'metadata', {});
util.privatize(this, 'baseUrl', config.baseUrl);
util.privatize(this, 'parent', config.parent); // Parent class.
util.privatize(this, 'id', config.id); // Name or ID (e.g. dataset ID, bucket name, etc.)
util.privatize(this, 'createMethod', config.createMethod);
util.privatize(this, 'methods', config.methods || {});
util.privatize(this, 'interceptors', []);
util.privatize(this, 'Promise', this.parent.Promise);
if (config.methods) {
const allMethodNames = Object.keys(ServiceObject.prototype);
allMethodNames
.filter(function(methodName) {
return (
// All ServiceObjects need `request`.
!/^request/.test(methodName) &&
// The ServiceObject didn't redefine the method.
self[methodName] === ServiceObject.prototype[methodName] &&
// This method isn't wanted.
!config.methods[methodName]
);
})
.forEach(function(methodName) {
self[methodName] = undefined;
});
}
}
/**
* Create the object.
*
* @param {object=} options - Configuration object.
* @param {function} callback - The callback function.
* @param {?error} callback.err - An error returned while making this request.
* @param {object} callback.instance - The instance.
* @param {object} callback.apiResponse - The full API response.
*/
ServiceObject.prototype.create = function(options, callback) {
const self = this;
const args = [this.id];
if (is.fn(options)) {
callback = options;
}
if (is.object(options)) {
args.push(options);
}
// Wrap the callback to return *this* instance of the object, not the newly-
// created one.
function onCreate(err, instance) {
const args = [].slice.call(arguments);
if (!err) {
self.metadata = instance.metadata;
args[1] = self; // replace the created `instance` with this one.
}
callback.apply(null, args);
}
args.push(onCreate);
this.createMethod.apply(null, args);
};
/**
* Delete the object.
*
* @param {function=} callback - The callback function.
* @param {?error} callback.err - An error returned while making this request.
* @param {object} callback.apiResponse - The full API response.
*/
ServiceObject.prototype.delete = function(callback) {
const methodConfig = this.methods.delete || {};
callback = callback || util.noop;
const reqOpts = extend(
{
method: 'DELETE',
uri: '',
},
methodConfig.reqOpts
);
// The `request` method may have been overridden to hold any special behavior.
// Ensure we call the original `request` method.
ServiceObject.prototype.request.call(this, reqOpts, function(err, resp) {
callback(err, resp);
});
};
/**
* Check if the object exists.
*
* @param {function} callback - The callback function.
* @param {?error} callback.err - An error returned while making this request.
* @param {boolean} callback.exists - Whether the object exists or not.
*/
ServiceObject.prototype.exists = function(callback) {
this.get(function(err) {
if (err) {
if (err.code === 404) {
callback(null, false);
} else {
callback(err);
}
return;
}
callback(null, true);
});
};
/**
* Get the object if it exists. Optionally have the object created if an options
* object is provided with `autoCreate: true`.
*
* @param {object=} config - The configuration object that will be used to
* create the object if necessary.
* @param {boolean} config.autoCreate - Create the object if it doesn't already
* exist.
* @param {function} callback - The callback function.
* @param {?error} callback.err - An error returned while making this request.
* @param {object} callback.instance - The instance.
* @param {object} callback.apiResponse - The full API response.
*/
ServiceObject.prototype.get = function(config, callback) {
const self = this;
if (is.fn(config)) {
callback = config;
config = {};
}
config = config || {};
const autoCreate = config.autoCreate && is.fn(this.create);
delete config.autoCreate;
function onCreate(err, instance, apiResponse) {
if (err) {
if (err.code === 409) {
self.get(config, callback);
return;
}
callback(err, null, apiResponse);
return;
}
callback(null, instance, apiResponse);
}
this.getMetadata(function(err, metadata) {
if (err) {
if (err.code === 404 && autoCreate) {
const args = [];
if (!is.empty(config)) {
args.push(config);
}
args.push(onCreate);
self.create.apply(self, args);
return;
}
callback(err, null, metadata);
return;
}
callback(null, self, metadata);
});
};
/**
* Get the metadata of this object.
*
* @param {function} callback - The callback function.
* @param {?error} callback.err - An error returned while making this request.
* @param {object} callback.metadata - The metadata for this object.
* @param {object} callback.apiResponse - The full API response.
*/
ServiceObject.prototype.getMetadata = function(callback) {
const self = this;
const methodConfig = this.methods.getMetadata || {};
const reqOpts = extend(
{
uri: '',
},
methodConfig.reqOpts
);
// The `request` method may have been overridden to hold any special behavior.
// Ensure we call the original `request` method.
ServiceObject.prototype.request.call(this, reqOpts, function(err, resp) {
if (err) {
callback(err, null, resp);
return;
}
self.metadata = resp;
callback(null, self.metadata, resp);
});
};
/**
* Set the metadata for this object.
*
* @param {object} metadata - The metadata to set on this object.
* @param {function=} callback - The callback function.
* @param {?error} callback.err - An error returned while making this request.
* @param {object} callback.instance - The instance.
* @param {object} callback.apiResponse - The full API response.
*/
ServiceObject.prototype.setMetadata = function(metadata, callback) {
const self = this;
callback = callback || util.noop;
const methodConfig = this.methods.setMetadata || {};
const reqOpts = extend(
true,
{
method: 'PATCH',
uri: '',
json: metadata,
},
methodConfig.reqOpts
);
// The `request` method may have been overridden to hold any special behavior.
// Ensure we call the original `request` method.
ServiceObject.prototype.request.call(this, reqOpts, function(err, resp) {
if (err) {
callback(err, resp);
return;
}
self.metadata = resp;
callback(null, resp);
});
};
/**
* Make an authenticated API request.
*
* @private
*
* @param {object} reqOpts - Request options that are passed to `request`.
* @param {string} reqOpts.uri - A URI relative to the baseUrl.
* @param {function} callback - The callback function passed to `request`.
*/
ServiceObject.prototype.request_ = function(reqOpts, callback) {
reqOpts = extend(true, {}, reqOpts);
const isAbsoluteUrl = reqOpts.uri.indexOf('http') === 0;
const uriComponents = [this.baseUrl, this.id || '', reqOpts.uri];
if (isAbsoluteUrl) {
uriComponents.splice(0, uriComponents.indexOf(reqOpts.uri));
}
reqOpts.uri = uriComponents
.filter(exec('trim')) // Limit to non-empty strings.
.map(function(uriComponent) {
const trimSlashesRegex = /^\/*|\/*$/g;
return uriComponent.replace(trimSlashesRegex, '');
})
.join('/');
const childInterceptors = arrify(reqOpts.interceptors_);
const localInterceptors = [].slice.call(this.interceptors);
reqOpts.interceptors_ = childInterceptors.concat(localInterceptors);
if (!callback) {
return this.parent.requestStream(reqOpts);
}
this.parent.request(reqOpts, callback);
};
/**
* Make an authenticated API request.
*
* @private
*
* @param {object} reqOpts - Request options that are passed to `request`.
* @param {string} reqOpts.uri - A URI relative to the baseUrl.
* @param {function} callback - The callback function passed to `request`.
*/
ServiceObject.prototype.request = function(reqOpts, callback) {
ServiceObject.prototype.request_.call(this, reqOpts, callback);
};
/**
* Make an authenticated API request.
*
* @private
*
* @param {object} reqOpts - Request options that are passed to `request`.
* @param {string} reqOpts.uri - A URI relative to the baseUrl.
*/
ServiceObject.prototype.requestStream = function(reqOpts) {
return ServiceObject.prototype.request_.call(this, reqOpts);
};
/*! Developer Documentation
*
* All async methods (except for streams) will return a Promise in the event
* that a callback is omitted.
*/
util.promisifyAll(ServiceObject);
module.exports = ServiceObject;

View File

@ -0,0 +1,200 @@
/*!
* Copyright 2015 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.
*/
/*!
* @module common/service
*/
'use strict';
const arrify = require('arrify');
const extend = require('extend');
/**
* @type {module:common/util}
* @private
*/
const util = require('./util.js');
const PROJECT_ID_TOKEN = '{{projectId}}';
/**
* Service is a base class, meant to be inherited from by a "service," like
* BigQuery or Storage.
*
* This handles making authenticated requests by exposing a `makeReq_` function.
*
* @constructor
* @alias module:common/service
*
* @param {object} config - Configuration object.
* @param {string} config.baseUrl - The base URL to make API requests to.
* @param {string[]} config.scopes - The scopes required for the request.
* @param {object=} options - [Configuration object](#/docs).
*/
function Service(config, options) {
options = options || {};
util.privatize(this, 'baseUrl', config.baseUrl);
util.privatize(this, 'globalInterceptors', arrify(options.interceptors_));
util.privatize(this, 'interceptors', []);
util.privatize(this, 'packageJson', config.packageJson);
util.privatize(this, 'projectId', options.projectId || PROJECT_ID_TOKEN);
util.privatize(this, 'projectIdRequired', config.projectIdRequired !== false);
util.privatize(this, 'Promise', options.promise || Promise);
const reqCfg = extend({}, config, {
projectIdRequired: this.projectIdRequired,
projectId: this.projectId,
credentials: options.credentials,
keyFile: options.keyFilename,
email: options.email,
token: options.token,
});
util.privatize(
this,
'makeAuthenticatedRequest',
util.makeAuthenticatedRequestFactory(reqCfg)
);
util.privatize(this, 'authClient', this.makeAuthenticatedRequest.authClient);
util.privatize(
this,
'getCredentials',
this.makeAuthenticatedRequest.getCredentials
);
const isCloudFunctionEnv = !!process.env.FUNCTION_NAME;
if (isCloudFunctionEnv) {
this.interceptors.push({
request: function(reqOpts) {
reqOpts.forever = false;
return reqOpts;
},
});
}
}
/**
* Get and update the Service's project ID.
*
* @param {function} callback - The callback function.
*/
Service.prototype.getProjectId = function(callback) {
const self = this;
this.authClient.getProjectId(function(err, projectId) {
if (err) {
callback(err);
return;
}
if (self.projectId === PROJECT_ID_TOKEN && projectId) {
self.projectId = projectId;
}
callback(null, self.projectId);
});
};
/**
* Make an authenticated API request.
*
* @private
*
* @param {object} reqOpts - Request options that are passed to `request`.
* @param {string} reqOpts.uri - A URI relative to the baseUrl.
* @param {function} callback - The callback function passed to `request`.
*/
Service.prototype.request_ = function(reqOpts, callback) {
reqOpts = extend(true, {}, reqOpts);
const isAbsoluteUrl = reqOpts.uri.indexOf('http') === 0;
const uriComponents = [this.baseUrl];
if (this.projectIdRequired) {
uriComponents.push('projects');
uriComponents.push(this.projectId);
}
uriComponents.push(reqOpts.uri);
if (isAbsoluteUrl) {
uriComponents.splice(0, uriComponents.indexOf(reqOpts.uri));
}
reqOpts.uri = uriComponents
.map(function(uriComponent) {
const trimSlashesRegex = /^\/*|\/*$/g;
return uriComponent.replace(trimSlashesRegex, '');
})
.join('/')
// Some URIs have colon separators.
// Bad: https://.../projects/:list
// Good: https://.../projects:list
.replace(/\/:/g, ':');
// Interceptors should be called in the order they were assigned.
const combinedInterceptors = [].slice
.call(this.globalInterceptors)
.concat(this.interceptors)
.concat(arrify(reqOpts.interceptors_));
let interceptor;
while ((interceptor = combinedInterceptors.shift()) && interceptor.request) {
reqOpts = interceptor.request(reqOpts);
}
delete reqOpts.interceptors_;
const pkg = this.packageJson;
reqOpts.headers = extend({}, reqOpts.headers, {
'User-Agent': util.getUserAgentFromPackageJson(pkg),
'x-goog-api-client': `gl-node/${process.versions.node} gccl/${pkg.version}`,
});
return this.makeAuthenticatedRequest(reqOpts, callback);
};
/**
* Make an authenticated API request.
*
* @private
*
* @param {object} reqOpts - Request options that are passed to `request`.
* @param {string} reqOpts.uri - A URI relative to the baseUrl.
* @param {function} callback - The callback function passed to `request`.
*/
Service.prototype.request = function(reqOpts, callback) {
Service.prototype.request_.call(this, reqOpts, callback);
};
/**
* Make an authenticated API request.
*
* @private
*
* @param {object} reqOpts - Request options that are passed to `request`.
* @param {string} reqOpts.uri - A URI relative to the baseUrl.
*/
Service.prototype.requestStream = function(reqOpts) {
return Service.prototype.request_.call(this, reqOpts);
};
module.exports = Service;

View File

@ -0,0 +1,830 @@
/**
* Copyright 2014 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.
*/
/*!
* @module common/util
*/
'use strict';
const createErrorClass = require('create-error-class');
const duplexify = require('duplexify');
const ent = require('ent');
const extend = require('extend');
const googleAuth = require('google-auto-auth');
const is = require('is');
const request = require('request').defaults({
timeout: 60000,
gzip: true,
forever: true,
pool: {
maxSockets: Infinity,
},
});
const retryRequest = require('retry-request');
const streamEvents = require('stream-events');
const through = require('through2');
const uniq = require('array-uniq');
const util = module.exports;
/**
* Custom error type for missing project ID errors.
*/
util.MissingProjectIdError = createErrorClass(
'MissingProjectIdError',
function() {
this.message = `Sorry, we cannot connect to Cloud Services without a project
ID. You may specify one with an environment variable named
"GOOGLE_CLOUD_PROJECT".`.replace(/ +/g, ' ');
}
);
/**
* No op.
*
* @example
* function doSomething(callback) {
* callback = callback || noop;
* }
*/
function noop() {}
util.noop = noop;
/**
* Custom error type for API errors.
*
* @param {object} errorBody - Error object.
*/
util.ApiError = createErrorClass('ApiError', function(errorBody) {
this.code = errorBody.code;
this.errors = errorBody.errors;
this.response = errorBody.response;
try {
this.errors = JSON.parse(this.response.body).error.errors;
} catch (e) {
this.errors = errorBody.errors;
}
const messages = [];
if (errorBody.message) {
messages.push(errorBody.message);
}
if (this.errors && this.errors.length === 1) {
messages.push(this.errors[0].message);
} else if (this.response && this.response.body) {
messages.push(ent.decode(errorBody.response.body.toString()));
} else if (!errorBody.message) {
messages.push('Error during request.');
}
this.message = uniq(messages).join(' - ');
});
/**
* Custom error type for partial errors returned from the API.
*
* @param {object} b - Error object.
*/
util.PartialFailureError = createErrorClass('PartialFailureError', function(b) {
const errorObject = b;
this.errors = errorObject.errors;
this.response = errorObject.response;
const defaultErrorMessage = 'A failure occurred during this request.';
this.message = errorObject.message || defaultErrorMessage;
});
/**
* Uniformly process an API response.
*
* @param {*} err - Error value.
* @param {*} resp - Response value.
* @param {*} body - Body value.
* @param {function} callback - The callback function.
*/
function handleResp(err, resp, body, callback) {
callback = callback || util.noop;
const parsedResp = extend(
true,
{err: err || null},
resp && util.parseHttpRespMessage(resp),
body && util.parseHttpRespBody(body)
);
callback(parsedResp.err, parsedResp.body, parsedResp.resp);
}
util.handleResp = handleResp;
/**
* Sniff an incoming HTTP response message for errors.
*
* @param {object} httpRespMessage - An incoming HTTP response message from
* `request`.
* @return {object} parsedHttpRespMessage - The parsed response.
* @param {?error} parsedHttpRespMessage.err - An error detected.
* @param {object} parsedHttpRespMessage.resp - The original response object.
*/
function parseHttpRespMessage(httpRespMessage) {
const parsedHttpRespMessage = {
resp: httpRespMessage,
};
if (httpRespMessage.statusCode < 200 || httpRespMessage.statusCode > 299) {
// Unknown error. Format according to ApiError standard.
parsedHttpRespMessage.err = new util.ApiError({
errors: [],
code: httpRespMessage.statusCode,
message: httpRespMessage.statusMessage,
response: httpRespMessage,
});
}
return parsedHttpRespMessage;
}
util.parseHttpRespMessage = parseHttpRespMessage;
/**
* Parse the response body from an HTTP request.
*
* @param {object} body - The response body.
* @return {object} parsedHttpRespMessage - The parsed response.
* @param {?error} parsedHttpRespMessage.err - An error detected.
* @param {object} parsedHttpRespMessage.body - The original body value provided
* will try to be JSON.parse'd. If it's successful, the parsed value will be
* returned here, otherwise the original value.
*/
function parseHttpRespBody(body) {
const parsedHttpRespBody = {
body: body,
};
if (is.string(body)) {
try {
parsedHttpRespBody.body = JSON.parse(body);
} catch (err) {
parsedHttpRespBody.err = new util.ApiError('Cannot parse JSON response');
}
}
if (parsedHttpRespBody.body && parsedHttpRespBody.body.error) {
// Error from JSON API.
parsedHttpRespBody.err = new util.ApiError(parsedHttpRespBody.body.error);
}
return parsedHttpRespBody;
}
util.parseHttpRespBody = parseHttpRespBody;
/**
* Take a Duplexify stream, fetch an authenticated connection header, and create
* an outgoing writable stream.
*
* @param {Duplexify} dup - Duplexify stream.
* @param {object} options - Configuration object.
* @param {module:common/connection} options.connection - A connection instance,
* used to get a token with and send the request through.
* @param {object} options.metadata - Metadata to send at the head of the
* request.
* @param {object} options.request - Request object, in the format of a standard
* Node.js http.request() object.
* @param {string=} options.request.method - Default: "POST".
* @param {string=} options.request.qs.uploadType - Default: "multipart".
* @param {string=} options.streamContentType - Default:
* "application/octet-stream".
* @param {function} onComplete - Callback, executed after the writable Request
* stream has completed.
*/
function makeWritableStream(dup, options, onComplete) {
onComplete = onComplete || util.noop;
const writeStream = through();
dup.setWritable(writeStream);
const defaultReqOpts = {
method: 'POST',
qs: {
uploadType: 'multipart',
},
};
const metadata = options.metadata || {};
const reqOpts = extend(true, defaultReqOpts, options.request, {
multipart: [
{
'Content-Type': 'application/json',
body: JSON.stringify(metadata),
},
{
'Content-Type': metadata.contentType || 'application/octet-stream',
body: writeStream,
},
],
});
options.makeAuthenticatedRequest(reqOpts, {
onAuthenticated: function(err, authenticatedReqOpts) {
if (err) {
dup.destroy(err);
return;
}
request(authenticatedReqOpts, function(err, resp, body) {
util.handleResp(err, resp, body, function(err, data) {
if (err) {
dup.destroy(err);
return;
}
dup.emit('response', resp);
onComplete(data);
});
});
},
});
}
util.makeWritableStream = makeWritableStream;
/**
* Returns true if the API request should be retried, given the error that was
* given the first time the request was attempted. This is used for rate limit
* related errors as well as intermittent server errors.
*
* @param {error} err - The API error to check if it is appropriate to retry.
* @return {boolean} True if the API request should be retried, false otherwise.
*/
function shouldRetryRequest(err) {
if (err) {
if ([429, 500, 502, 503].indexOf(err.code) !== -1) {
return true;
}
if (err.errors) {
for (const i in err.errors) {
const reason = err.errors[i].reason;
if (reason === 'rateLimitExceeded') {
return true;
}
if (reason === 'userRateLimitExceeded') {
return true;
}
}
}
}
return false;
}
util.shouldRetryRequest = shouldRetryRequest;
/**
* Get a function for making authenticated requests.
*
* @throws {Error} If a projectId is requested, but not able to be detected.
*
* @param {object} config - Configuration object.
* @param {boolean=} config.autoRetry - Automatically retry requests if the
* response is related to rate limits or certain intermittent server errors.
* We will exponentially backoff subsequent requests by default. (default:
* true)
* @param {object=} config.credentials - Credentials object.
* @param {boolean=} config.customEndpoint - If true, just return the provided
* request options. Default: false.
* @param {string=} config.email - Account email address, required for PEM/P12
* usage.
* @param {number=} config.maxRetries - Maximum number of automatic retries
* attempted before returning the error. (default: 3)
* @param {string=} config.keyFile - Path to a .json, .pem, or .p12 keyfile.
* @param {array} config.scopes - Array of scopes required for the API.
*/
function makeAuthenticatedRequestFactory(config) {
config = config || {};
const googleAutoAuthConfig = extend({}, config);
if (googleAutoAuthConfig.projectId === '{{projectId}}') {
delete googleAutoAuthConfig.projectId;
}
const authClient = googleAuth(googleAutoAuthConfig);
/**
* The returned function that will make an authenticated request.
*
* @param {type} reqOpts - Request options in the format `request` expects.
* @param {object|function} options - Configuration object or callback
* function.
* @param {function=} options.onAuthenticated - If provided, a request will
* not be made. Instead, this function is passed the error & authenticated
* request options.
*/
function makeAuthenticatedRequest(reqOpts, options) {
let stream;
const reqConfig = extend({}, config);
let activeRequest_;
if (!options) {
stream = duplexify();
reqConfig.stream = stream;
}
function onAuthenticated(err, authenticatedReqOpts) {
const autoAuthFailed =
err &&
err.message.indexOf('Could not load the default credentials') > -1;
if (autoAuthFailed) {
// Even though authentication failed, the API might not actually care.
authenticatedReqOpts = reqOpts;
}
if (!err || autoAuthFailed) {
let projectId = authClient.projectId;
if (config.projectId && config.projectId !== '{{projectId}}') {
projectId = config.projectId;
}
try {
authenticatedReqOpts = util.decorateRequest(
authenticatedReqOpts,
projectId
);
err = null;
} catch (e) {
// A projectId was required, but we don't have one.
// Re-use the "Could not load the default credentials error" if auto
// auth failed.
err = err || e;
}
}
if (err) {
if (stream) {
stream.destroy(err);
} else {
(options.onAuthenticated || options)(err);
}
return;
}
if (options && options.onAuthenticated) {
options.onAuthenticated(null, authenticatedReqOpts);
} else {
activeRequest_ = util.makeRequest(
authenticatedReqOpts,
reqConfig,
options
);
}
}
if (reqConfig.customEndpoint) {
// Using a custom API override. Do not use `google-auto-auth` for
// authentication. (ex: connecting to a local Datastore server)
onAuthenticated(null, reqOpts);
} else {
authClient.authorizeRequest(reqOpts, onAuthenticated);
}
if (stream) {
return stream;
}
return {
abort: function() {
if (activeRequest_) {
activeRequest_.abort();
activeRequest_ = null;
}
},
};
}
makeAuthenticatedRequest.getCredentials = authClient.getCredentials.bind(
authClient
);
makeAuthenticatedRequest.authClient = authClient;
return makeAuthenticatedRequest;
}
util.makeAuthenticatedRequestFactory = makeAuthenticatedRequestFactory;
/**
* Make a request through the `retryRequest` module with built-in error handling
* and exponential back off.
*
* @param {object} reqOpts - Request options in the format `request` expects.
* @param {object=} config - Configuration object.
* @param {boolean=} config.autoRetry - Automatically retry requests if the
* response is related to rate limits or certain intermittent server errors.
* We will exponentially backoff subsequent requests by default. (default:
* true)
* @param {number=} config.maxRetries - Maximum number of automatic retries
* attempted before returning the error. (default: 3)
* @param {function} callback - The callback function.
*/
function makeRequest(reqOpts, config, callback) {
if (is.fn(config)) {
callback = config;
config = {};
}
config = config || {};
const options = {
request: request,
retries: config.autoRetry !== false ? config.maxRetries || 3 : 0,
shouldRetryFn: function(httpRespMessage) {
const err = util.parseHttpRespMessage(httpRespMessage).err;
return err && util.shouldRetryRequest(err);
},
};
if (config.stream) {
const dup = config.stream;
let requestStream;
const isGetRequest = (reqOpts.method || 'GET').toUpperCase() === 'GET';
if (isGetRequest) {
requestStream = retryRequest(reqOpts, options);
dup.setReadable(requestStream);
} else {
// Streaming writable HTTP requests cannot be retried.
requestStream = request(reqOpts);
dup.setWritable(requestStream);
}
// Replay the Request events back to the stream.
requestStream
.on('error', dup.destroy.bind(dup))
.on('response', dup.emit.bind(dup, 'response'))
.on('complete', dup.emit.bind(dup, 'complete'));
dup.abort = requestStream.abort;
} else {
return retryRequest(reqOpts, options, function(err, response, body) {
util.handleResp(err, response, body, callback);
});
}
}
util.makeRequest = makeRequest;
/**
* Decorate the options about to be made in a request.
*
* @param {object} reqOpts - The options to be passed to `request`.
* @param {string} projectId - The project ID.
* @return {object} reqOpts - The decorated reqOpts.
*/
function decorateRequest(reqOpts, projectId) {
delete reqOpts.autoPaginate;
delete reqOpts.autoPaginateVal;
delete reqOpts.objectMode;
if (is.object(reqOpts.qs)) {
delete reqOpts.qs.autoPaginate;
delete reqOpts.qs.autoPaginateVal;
reqOpts.qs = util.replaceProjectIdToken(reqOpts.qs, projectId);
}
if (is.object(reqOpts.json)) {
delete reqOpts.json.autoPaginate;
delete reqOpts.json.autoPaginateVal;
reqOpts.json = util.replaceProjectIdToken(reqOpts.json, projectId);
}
reqOpts.uri = util.replaceProjectIdToken(reqOpts.uri, projectId);
return reqOpts;
}
util.decorateRequest = decorateRequest;
/**
* Populate the `{{projectId}}` placeholder.
*
* @throws {Error} If a projectId is required, but one is not provided.
*
* @param {*} - Any input value that may contain a placeholder. Arrays and
* objects will be looped.
* @param {string} projectId - A projectId. If not provided
* @return {*} - The original argument with all placeholders populated.
*/
function replaceProjectIdToken(value, projectId) {
if (is.array(value)) {
value = value.map(function(val) {
return replaceProjectIdToken(val, projectId);
});
}
if (is.object(value) && is.fn(value.hasOwnProperty)) {
for (const opt in value) {
if (value.hasOwnProperty(opt)) {
value[opt] = replaceProjectIdToken(value[opt], projectId);
}
}
}
if (is.string(value) && value.indexOf('{{projectId}}') > -1) {
if (!projectId || projectId === '{{projectId}}') {
throw new util.MissingProjectIdError();
}
value = value.replace(/{{projectId}}/g, projectId);
}
return value;
}
util.replaceProjectIdToken = replaceProjectIdToken;
/**
* Extend a global configuration object with user options provided at the time
* of sub-module instantiation.
*
* Connection details currently come in two ways: `credentials` or
* `keyFilename`. Because of this, we have a special exception when overriding a
* global configuration object. If a user provides either to the global
* configuration, then provides another at submodule instantiation-time, the
* latter is preferred.
*
* @param {object} globalConfig - The global configuration object.
* @param {object=} overrides - The instantiation-time configuration object.
* @return {object}
*/
function extendGlobalConfig(globalConfig, overrides) {
globalConfig = globalConfig || {};
overrides = overrides || {};
const defaultConfig = {};
if (process.env.GCLOUD_PROJECT) {
defaultConfig.projectId = process.env.GCLOUD_PROJECT;
}
const options = extend({}, globalConfig);
const hasGlobalConnection = options.credentials || options.keyFilename;
const isOverridingConnection = overrides.credentials || overrides.keyFilename;
if (hasGlobalConnection && isOverridingConnection) {
delete options.credentials;
delete options.keyFilename;
}
const extendedConfig = extend(true, defaultConfig, options, overrides);
// Preserve the original (not cloned) interceptors.
extendedConfig.interceptors_ = globalConfig.interceptors_;
return extendedConfig;
}
util.extendGlobalConfig = extendGlobalConfig;
/**
* Merge and validate API configurations.
*
* @param {object} globalContext - gcloud-level context.
* @param {object} globalContext.config_ - gcloud-level configuration.
* @param {object} localConfig - Service-level configurations.
* @return {object} config - Merged and validated configuration.
*/
function normalizeArguments(globalContext, localConfig) {
const globalConfig = globalContext && globalContext.config_;
return util.extendGlobalConfig(globalConfig, localConfig);
}
util.normalizeArguments = normalizeArguments;
/**
* Limit requests according to a `maxApiCalls` limit.
*
* @param {function} makeRequestFn - The function that will be called.
* @param {object=} options - Configuration object.
* @param {number} options.maxApiCalls - The maximum number of API calls to
* make.
* @param {object} options.streamOptions - Options to pass to the Stream
* constructor.
*/
function createLimiter(makeRequestFn, options) {
options = options || {};
const stream = streamEvents(through.obj(options.streamOptions));
let requestsMade = 0;
let requestsToMake = -1;
if (is.number(options.maxApiCalls)) {
requestsToMake = options.maxApiCalls;
}
return {
makeRequest: function() {
requestsMade++;
if (requestsToMake >= 0 && requestsMade > requestsToMake) {
stream.push(null);
return;
}
makeRequestFn.apply(null, arguments);
return stream;
},
stream: stream,
};
}
util.createLimiter = createLimiter;
function isCustomType(unknown, module) {
function getConstructorName(obj) {
return obj.constructor && obj.constructor.name.toLowerCase();
}
const moduleNameParts = module.split('/');
const parentModuleName =
moduleNameParts[0] && moduleNameParts[0].toLowerCase();
const subModuleName = moduleNameParts[1] && moduleNameParts[1].toLowerCase();
if (subModuleName && getConstructorName(unknown) !== subModuleName) {
return false;
}
let walkingModule = unknown;
do {
if (getConstructorName(walkingModule) === parentModuleName) {
return true;
}
} while ((walkingModule = walkingModule.parent));
return false;
}
util.isCustomType = isCustomType;
/**
* Create a properly-formatted User-Agent string from a package.json file.
*
* @param {object} packageJson - A module's package.json file.
* @return {string} userAgent - The formatted User-Agent string.
*/
function getUserAgentFromPackageJson(packageJson) {
const hyphenatedPackageName = packageJson.name
.replace('@google-cloud', 'gcloud-node') // For legacy purposes.
.replace('/', '-'); // For UA spec-compliance purposes.
return hyphenatedPackageName + '/' + packageJson.version;
}
util.getUserAgentFromPackageJson = getUserAgentFromPackageJson;
/**
* Wraps a callback style function to conditionally return a promise.
*
* @param {function} originalMethod - The method to promisify.
* @param {object=} options - Promise options.
* @param {boolean} options.singular - Resolve the promise with single arg
* instead of an array.
* @return {function} wrapped
*/
function promisify(originalMethod, options) {
if (originalMethod.promisified_) {
return originalMethod;
}
options = options || {};
const slice = Array.prototype.slice;
const wrapper = function() {
const context = this;
let last;
for (last = arguments.length - 1; last >= 0; last--) {
const arg = arguments[last];
if (is.undefined(arg)) {
continue; // skip trailing undefined.
}
if (!is.fn(arg)) {
break; // non-callback last argument found.
}
return originalMethod.apply(context, arguments);
}
// peel trailing undefined.
const args = slice.call(arguments, 0, last + 1);
let PromiseCtor = Promise;
// Because dedupe will likely create a single install of
// @google-cloud/common to be shared amongst all modules, we need to
// localize it at the Service level.
if (context && context.Promise) {
PromiseCtor = context.Promise;
}
return new PromiseCtor(function(resolve, reject) {
args.push(function() {
const callbackArgs = slice.call(arguments);
const err = callbackArgs.shift();
if (err) {
return reject(err);
}
if (options.singular && callbackArgs.length === 1) {
resolve(callbackArgs[0]);
} else {
resolve(callbackArgs);
}
});
originalMethod.apply(context, args);
});
};
wrapper.promisified_ = true;
return wrapper;
}
util.promisify = promisify;
/**
* Promisifies certain Class methods. This will not promisify private or
* streaming methods.
*
* @param {module:common/service} Class - Service class.
* @param {object=} options - Configuration object.
*/
function promisifyAll(Class, options) {
const exclude = (options && options.exclude) || [];
const methods = Object.keys(Class.prototype).filter(function(methodName) {
return (
is.fn(Class.prototype[methodName]) && // is it a function?
!/(^_|(Stream|_)|promise$)/.test(methodName) && // is it promisable?
exclude.indexOf(methodName) === -1
); // is it blacklisted?
});
methods.forEach(function(methodName) {
const originalMethod = Class.prototype[methodName];
if (!originalMethod.promisified_) {
Class.prototype[methodName] = util.promisify(originalMethod, options);
}
});
}
util.promisifyAll = promisifyAll;
/**
* This will mask properties of an object from console.log.
*
* @param {object} object - The object to assign the property to.
* @param {string} propName - Property name.
* @param {*} value - Value.
*/
function privatize(object, propName, value) {
Object.defineProperty(object, propName, {value, writable: true});
}
util.privatize = privatize;