123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.Client = exports.setAccessToken = exports.setRefreshToken = void 0;
- const url_1 = require("url");
- const stream_1 = require("stream");
- const ProxyAgent = require("proxy-agent");
- const retry = require("retry");
- const abort_controller_1 = require("abort-controller");
- const node_fetch_1 = require("node-fetch");
- const util_1 = require("util");
- const auth = require("./auth");
- const error_1 = require("./error");
- const logger_1 = require("./logger");
- const responseToError_1 = require("./responseToError");
- const FormData = require("form-data");
- const pkg = require("../package.json");
- const CLI_VERSION = pkg.version;
- const GOOG_QUOTA_USER = "x-goog-quota-user";
- let accessToken = "";
- let refreshToken = "";
- function setRefreshToken(token = "") {
- refreshToken = token;
- }
- exports.setRefreshToken = setRefreshToken;
- function setAccessToken(token = "") {
- accessToken = token;
- }
- exports.setAccessToken = setAccessToken;
- function proxyURIFromEnv() {
- return (process.env.HTTPS_PROXY ||
- process.env.https_proxy ||
- process.env.HTTP_PROXY ||
- process.env.http_proxy ||
- undefined);
- }
- class Client {
- constructor(opts) {
- this.opts = opts;
- if (this.opts.auth === undefined) {
- this.opts.auth = true;
- }
- if (this.opts.urlPrefix.endsWith("/")) {
- this.opts.urlPrefix = this.opts.urlPrefix.substring(0, this.opts.urlPrefix.length - 1);
- }
- }
- get(path, options = {}) {
- const reqOptions = Object.assign(options, {
- method: "GET",
- path,
- });
- return this.request(reqOptions);
- }
- post(path, json, options = {}) {
- const reqOptions = Object.assign(options, {
- method: "POST",
- path,
- body: json,
- });
- return this.request(reqOptions);
- }
- patch(path, json, options = {}) {
- const reqOptions = Object.assign(options, {
- method: "PATCH",
- path,
- body: json,
- });
- return this.request(reqOptions);
- }
- put(path, json, options = {}) {
- const reqOptions = Object.assign(options, {
- method: "PUT",
- path,
- body: json,
- });
- return this.request(reqOptions);
- }
- delete(path, options = {}) {
- const reqOptions = Object.assign(options, {
- method: "DELETE",
- path,
- });
- return this.request(reqOptions);
- }
- async request(reqOptions) {
- if (!reqOptions.responseType) {
- reqOptions.responseType = "json";
- }
- if (reqOptions.responseType === "stream" && !reqOptions.resolveOnHTTPError) {
- throw new error_1.FirebaseError("apiv2 will not handle HTTP errors while streaming and you must set `resolveOnHTTPError` and check for res.status >= 400 on your own", { exit: 2 });
- }
- let internalReqOptions = Object.assign(reqOptions, {
- headers: new node_fetch_1.Headers(reqOptions.headers),
- });
- internalReqOptions = this.addRequestHeaders(internalReqOptions);
- if (this.opts.auth) {
- internalReqOptions = await this.addAuthHeader(internalReqOptions);
- }
- try {
- return await this.doRequest(internalReqOptions);
- }
- catch (thrown) {
- if (thrown instanceof error_1.FirebaseError) {
- throw thrown;
- }
- let err;
- if (thrown instanceof Error) {
- err = thrown;
- }
- else {
- err = new Error(thrown);
- }
- throw new error_1.FirebaseError(`Failed to make request: ${err.message}`, { original: err });
- }
- }
- addRequestHeaders(reqOptions) {
- if (!reqOptions.headers) {
- reqOptions.headers = new node_fetch_1.Headers();
- }
- reqOptions.headers.set("Connection", "keep-alive");
- if (!reqOptions.headers.has("User-Agent")) {
- reqOptions.headers.set("User-Agent", `FirebaseCLI/${CLI_VERSION}`);
- }
- reqOptions.headers.set("X-Client-Version", `FirebaseCLI/${CLI_VERSION}`);
- if (!reqOptions.headers.has("Content-Type")) {
- if (reqOptions.responseType === "json") {
- reqOptions.headers.set("Content-Type", "application/json");
- }
- }
- return reqOptions;
- }
- async addAuthHeader(reqOptions) {
- if (!reqOptions.headers) {
- reqOptions.headers = new node_fetch_1.Headers();
- }
- let token;
- if (isLocalInsecureRequest(this.opts.urlPrefix)) {
- token = "owner";
- }
- else {
- token = await this.getAccessToken();
- }
- reqOptions.headers.set("Authorization", `Bearer ${token}`);
- return reqOptions;
- }
- async getAccessToken() {
- if (accessToken) {
- return accessToken;
- }
- const data = (await auth.getAccessToken(refreshToken, []));
- return data.access_token;
- }
- requestURL(options) {
- const versionPath = this.opts.apiVersion ? `/${this.opts.apiVersion}` : "";
- return `${this.opts.urlPrefix}${versionPath}${options.path}`;
- }
- async doRequest(options) {
- var _a;
- if (!options.path.startsWith("/")) {
- options.path = "/" + options.path;
- }
- let fetchURL = this.requestURL(options);
- if (options.queryParams) {
- if (!(options.queryParams instanceof url_1.URLSearchParams)) {
- const sp = new url_1.URLSearchParams();
- for (const key of Object.keys(options.queryParams)) {
- const value = options.queryParams[key];
- sp.append(key, `${value}`);
- }
- options.queryParams = sp;
- }
- const queryString = options.queryParams.toString();
- if (queryString) {
- fetchURL += `?${queryString}`;
- }
- }
- const fetchOptions = {
- headers: options.headers,
- method: options.method,
- redirect: options.redirect,
- compress: options.compress,
- };
- if (this.opts.proxy) {
- fetchOptions.agent = new ProxyAgent(this.opts.proxy);
- }
- const envProxy = proxyURIFromEnv();
- if (envProxy) {
- fetchOptions.agent = new ProxyAgent(envProxy);
- }
- if (options.signal) {
- fetchOptions.signal = options.signal;
- }
- let reqTimeout;
- if (options.timeout) {
- const controller = new abort_controller_1.default();
- reqTimeout = setTimeout(() => {
- controller.abort();
- }, options.timeout);
- fetchOptions.signal = controller.signal;
- }
- if (typeof options.body === "string" || isStream(options.body)) {
- fetchOptions.body = options.body;
- }
- else if (options.body !== undefined) {
- fetchOptions.body = JSON.stringify(options.body);
- }
- const operationOptions = {
- retries: ((_a = options.retryCodes) === null || _a === void 0 ? void 0 : _a.length) ? 1 : 2,
- minTimeout: 1 * 1000,
- maxTimeout: 5 * 1000,
- };
- if (typeof options.retries === "number") {
- operationOptions.retries = options.retries;
- }
- if (typeof options.retryMinTimeout === "number") {
- operationOptions.minTimeout = options.retryMinTimeout;
- }
- if (typeof options.retryMaxTimeout === "number") {
- operationOptions.maxTimeout = options.retryMaxTimeout;
- }
- const operation = retry.operation(operationOptions);
- return await new Promise((resolve, reject) => {
- operation.attempt(async (currentAttempt) => {
- var _a;
- let res;
- let body;
- try {
- if (currentAttempt > 1) {
- logger_1.logger.debug(`*** [apiv2] Attempting the request again. Attempt number ${currentAttempt}`);
- }
- this.logRequest(options);
- try {
- res = await (0, node_fetch_1.default)(fetchURL, fetchOptions);
- }
- catch (thrown) {
- const err = thrown instanceof Error ? thrown : new Error(thrown);
- const isAbortError = err.name.includes("AbortError");
- if (isAbortError) {
- throw new error_1.FirebaseError(`Timeout reached making request to ${fetchURL}`, {
- original: err,
- });
- }
- throw new error_1.FirebaseError(`Failed to make request to ${fetchURL}`, { original: err });
- }
- finally {
- if (reqTimeout) {
- clearTimeout(reqTimeout);
- }
- }
- if (options.responseType === "json") {
- const text = await res.text();
- if (!text.length) {
- body = undefined;
- }
- else {
- try {
- body = JSON.parse(text);
- }
- catch (err) {
- this.logResponse(res, text, options);
- throw new error_1.FirebaseError(`Unable to parse JSON: ${err}`);
- }
- }
- }
- else if (options.responseType === "xml") {
- body = (await res.text());
- }
- else if (options.responseType === "stream") {
- body = res.body;
- }
- else {
- throw new error_1.FirebaseError(`Unable to interpret response. Please set responseType.`, {
- exit: 2,
- });
- }
- }
- catch (err) {
- return err instanceof error_1.FirebaseError ? reject(err) : reject(new error_1.FirebaseError(`${err}`));
- }
- this.logResponse(res, body, options);
- if (res.status >= 400) {
- if ((_a = options.retryCodes) === null || _a === void 0 ? void 0 : _a.includes(res.status)) {
- const err = (0, responseToError_1.responseToError)({ statusCode: res.status }, body) || undefined;
- if (operation.retry(err)) {
- return;
- }
- }
- if (!options.resolveOnHTTPError) {
- return reject((0, responseToError_1.responseToError)({ statusCode: res.status }, body));
- }
- }
- resolve({
- status: res.status,
- response: res,
- body,
- });
- });
- });
- }
- logRequest(options) {
- var _a, _b;
- let queryParamsLog = "[none]";
- if (options.queryParams) {
- queryParamsLog = "[omitted]";
- if (!((_a = options.skipLog) === null || _a === void 0 ? void 0 : _a.queryParams)) {
- queryParamsLog =
- options.queryParams instanceof url_1.URLSearchParams
- ? options.queryParams.toString()
- : JSON.stringify(options.queryParams);
- }
- }
- const logURL = this.requestURL(options);
- logger_1.logger.debug(`>>> [apiv2][query] ${options.method} ${logURL} ${queryParamsLog}`);
- const headers = options.headers;
- if (headers && headers.has(GOOG_QUOTA_USER)) {
- logger_1.logger.debug(`>>> [apiv2][(partial)header] ${options.method} ${logURL} x-goog-quota-user=${headers.get(GOOG_QUOTA_USER) || ""}`);
- }
- if (options.body !== undefined) {
- let logBody = "[omitted]";
- if (!((_b = options.skipLog) === null || _b === void 0 ? void 0 : _b.body)) {
- logBody = bodyToString(options.body);
- }
- logger_1.logger.debug(`>>> [apiv2][body] ${options.method} ${logURL} ${logBody}`);
- }
- }
- logResponse(res, body, options) {
- var _a;
- const logURL = this.requestURL(options);
- logger_1.logger.debug(`<<< [apiv2][status] ${options.method} ${logURL} ${res.status}`);
- let logBody = "[omitted]";
- if (!((_a = options.skipLog) === null || _a === void 0 ? void 0 : _a.resBody)) {
- logBody = bodyToString(body);
- }
- logger_1.logger.debug(`<<< [apiv2][body] ${options.method} ${logURL} ${logBody}`);
- }
- }
- exports.Client = Client;
- function isLocalInsecureRequest(urlPrefix) {
- const u = new url_1.URL(urlPrefix);
- return u.protocol === "http:";
- }
- function bodyToString(body) {
- if (isStream(body)) {
- return "[stream]";
- }
- else {
- try {
- return JSON.stringify(body);
- }
- catch (_) {
- return util_1.default.inspect(body);
- }
- }
- }
- function isStream(o) {
- return o instanceof stream_1.Readable || o instanceof FormData;
- }
|