This commit is contained in:
girinb
2025-05-29 15:41:51 +09:00
parent a1bd4f87a1
commit 485098cd1a
5611 changed files with 881685 additions and 0 deletions

View File

@@ -0,0 +1,273 @@
import { Request, Response } from "express";
import { DeploymentOptions, FailurePolicy, Schedule } from "./function-configuration";
export { Request, Response };
import { ManifestEndpoint, ManifestRequiredAPI } from "../runtime/manifest";
export { Change } from "../common/change";
/**
* Wire format for an event.
*/
export interface Event {
/**
* Wire format for an event context.
*/
context: {
eventId: string;
timestamp: string;
eventType: string;
resource: Resource;
domain?: string;
auth?: {
variable?: {
uid?: string;
token?: string;
};
admin: boolean;
};
};
/**
* Event data over wire.
*/
data: any;
}
/**
* The context in which an event occurred.
*
* @remarks
* An EventContext describes:
* - The time an event occurred.
* - A unique identifier of the event.
* - The resource on which the event occurred, if applicable.
* - Authorization of the request that triggered the event, if applicable and
* available.
*/
export interface EventContext<Params = Record<string, string>> {
/**
* Authentication information for the user that triggered the function.
*
* @remarks
* This object contains `uid` and `token` properties for authenticated users.
* For more detail including token keys, see the
* {@link https://firebase.google.com/docs/reference/rules/rules#properties | security rules reference}.
*
* This field is only populated for Realtime Database triggers and Callable
* functions. For an unauthenticated user, this field is null. For Firebase
* admin users and event types that do not provide user information, this field
* does not exist.
*/
auth?: {
token: object;
uid: string;
};
/**
* The level of permissions for a user.
*
* @remarks
* Valid values are:
*
* - `ADMIN`: Developer user or user authenticated via a service account.
*
* - `USER`: Known user.
*
* - `UNAUTHENTICATED`: Unauthenticated action
*
* - `null`: For event types that do not provide user information (all except
* Realtime Database).
*/
authType?: "ADMIN" | "USER" | "UNAUTHENTICATED";
/**
* The events unique identifier.
*/
eventId: string;
/**
* Type of event.
*
* @remarks
* Possible values are:
*
* - `google.analytics.event.log`
*
* - `google.firebase.auth.user.create`
*
* - `google.firebase.auth.user.delete`
*
* - `google.firebase.database.ref.write`
*
* - `google.firebase.database.ref.create`
*
* - `google.firebase.database.ref.update`
*
* - `google.firebase.database.ref.delete`
*
* - `google.firestore.document.write`
*
* - `google.firestore.document.create`
*
* - `google.firestore.document.update`
*
* - `google.firestore.document.delete`
*
* - `google.pubsub.topic.publish`
*
* - `google.firebase.remoteconfig.update`
*
* - `google.storage.object.finalize`
*
* - `google.storage.object.archive`
*
* - `google.storage.object.delete`
*
* - `google.storage.object.metadataUpdate`
*
* - `google.testing.testMatrix.complete`
*/
eventType: string;
/**
* An object containing the values of the wildcards in the `path` parameter
* provided to the {@link fireabase-functions.v1.database#ref | `ref()`} method for a Realtime Database trigger.
*/
params: Params;
/**
* The resource that emitted the event.
*
* @remarks
* Valid values are:
*
* Analytics: `projects/<projectId>/events/<analyticsEventType>`
*
* Realtime Database: `projects/_/instances/<databaseInstance>/refs/<databasePath>`
*
* Storage: `projects/_/buckets/<bucketName>/objects/<fileName>#<generation>`
*
* Authentication: `projects/<projectId>`
*
* Pub/Sub: `projects/<projectId>/topics/<topicName>`
*
* Because Realtime Database instances and Cloud Storage buckets are globally
* unique and not tied to the project, their resources start with `projects/_`.
* Underscore is not a valid project name.
*/
resource: Resource;
/**
* Timestamp for the event as an {@link https://www.ietf.org/rfc/rfc3339.txt | RFC 3339} string.
*/
timestamp: string;
}
/**
* Resource is a standard format for defining a resource
* (google.rpc.context.AttributeContext.Resource). In Cloud Functions, it is the
* resource that triggered the function - such as a storage bucket.
*/
export interface Resource {
/** The name of the service that this resource belongs to. */
service: string;
/**
* The stable identifier (name) of a resource on the service.
* A resource can be logically identified as "//{resource.service}/{resource.name}"
*/
name: string;
/**
* The type of the resource. The syntax is platform-specific because different platforms define their resources differently.
* For Google APIs, the type format must be "{service}/{kind}"
*/
type?: string;
/** Map of Resource's labels. */
labels?: {
[tag: string]: string;
};
}
/**
* TriggerAnnotion is used internally by the firebase CLI to understand what
* type of Cloud Function to deploy.
*/
interface TriggerAnnotation {
availableMemoryMb?: number;
blockingTrigger?: {
eventType: string;
options?: Record<string, unknown>;
};
eventTrigger?: {
eventType: string;
resource: string;
service: string;
};
failurePolicy?: FailurePolicy;
httpsTrigger?: {
invoker?: string[];
};
labels?: {
[key: string]: string;
};
regions?: string[];
schedule?: Schedule;
timeout?: string;
vpcConnector?: string;
vpcConnectorEgressSettings?: string;
serviceAccountEmail?: string;
ingressSettings?: string;
secrets?: string[];
}
/**
* A Runnable has a `run` method which directly invokes the user-defined
* function - useful for unit testing.
*/
export interface Runnable<T> {
/** Directly invoke the user defined function. */
run: (data: T, context: any) => PromiseLike<any> | any;
}
/**
* The function type for HTTPS triggers. This should be exported from your
* JavaScript file to define a Cloud Function.
*
* @remarks
* This type is a special JavaScript function which takes Express
* {@link https://expressjs.com/en/api.html#req | `Request` } and
* {@link https://expressjs.com/en/api.html#res | `Response` } objects as its only
* arguments.
*/
export interface HttpsFunction {
(req: Request, resp: Response): void | Promise<void>;
/** @alpha */
__trigger: TriggerAnnotation;
/** @alpha */
__endpoint: ManifestEndpoint;
/** @alpha */
__requiredAPIs?: ManifestRequiredAPI[];
}
/**
* The function type for Auth Blocking triggers.
*
* @remarks
* This type is a special JavaScript function for Auth Blocking triggers which takes Express
* {@link https://expressjs.com/en/api.html#req | `Request` } and
* {@link https://expressjs.com/en/api.html#res | `Response` } objects as its only
* arguments.
*/
export interface BlockingFunction {
/** @public */
(req: Request, resp: Response): void | Promise<void>;
/** @alpha */
__trigger: TriggerAnnotation;
/** @alpha */
__endpoint: ManifestEndpoint;
/** @alpha */
__requiredAPIs?: ManifestRequiredAPI[];
}
/**
* The function type for all non-HTTPS triggers. This should be exported
* from your JavaScript file to define a Cloud Function.
*
* This type is a special JavaScript function which takes a templated
* `Event` object as its only argument.
*/
export interface CloudFunction<T> extends Runnable<T> {
(input: any, context?: any): PromiseLike<any> | any;
/** @alpha */
__trigger: TriggerAnnotation;
/** @alpha */
__endpoint: ManifestEndpoint;
/** @alpha */
__requiredAPIs?: ManifestRequiredAPI[];
}
/** @hidden */
export declare function optionsToTrigger(options: DeploymentOptions): any;
export declare function optionsToEndpoint(options: DeploymentOptions): ManifestEndpoint;

View File

@@ -0,0 +1,257 @@
"use strict";
// The MIT License (MIT)
//
// Copyright (c) 2017 Firebase
//
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.optionsToEndpoint = exports.optionsToTrigger = exports.makeCloudFunction = exports.Change = void 0;
const logger_1 = require("../logger");
const function_configuration_1 = require("./function-configuration");
const encoding_1 = require("../common/encoding");
const manifest_1 = require("../runtime/manifest");
const options_1 = require("../common/options");
const types_1 = require("../params/types");
const onInit_1 = require("../common/onInit");
var change_1 = require("../common/change");
Object.defineProperty(exports, "Change", { enumerable: true, get: function () { return change_1.Change; } });
/** @internal */
const WILDCARD_REGEX = new RegExp("{[^/{}]*}", "g");
/** @internal */
function makeCloudFunction({ contextOnlyHandler, dataConstructor = (raw) => raw.data, eventType, handler, labels = {}, legacyEventType, options = {}, provider, service, triggerResource, }) {
handler = (0, onInit_1.withInit)(handler !== null && handler !== void 0 ? handler : contextOnlyHandler);
const cloudFunction = (data, context) => {
if (legacyEventType && context.eventType === legacyEventType) {
/*
* v1beta1 event flow has different format for context, transform them to
* new format.
*/
context.eventType = provider + "." + eventType;
context.resource = {
service,
name: context.resource,
};
}
const event = {
data,
context,
};
if (provider === "google.firebase.database") {
context.authType = _detectAuthType(event);
if (context.authType !== "ADMIN") {
context.auth = _makeAuth(event, context.authType);
}
else {
delete context.auth;
}
}
if (triggerResource() == null) {
Object.defineProperty(context, "params", {
get: () => {
throw new Error("context.params is not available when using the handler namespace.");
},
});
}
else {
context.params = context.params || _makeParams(context, triggerResource);
}
let promise;
if (labels && labels["deployment-scheduled"]) {
// Scheduled function do not have meaningful data, so exclude it
promise = contextOnlyHandler(context);
}
else {
const dataOrChange = dataConstructor(event);
promise = handler(dataOrChange, context);
}
if (typeof promise === "undefined") {
(0, logger_1.warn)("Function returned undefined, expected Promise or value");
}
return Promise.resolve(promise);
};
Object.defineProperty(cloudFunction, "__trigger", {
get: () => {
if (triggerResource() == null) {
return {};
}
const trigger = {
...optionsToTrigger(options),
eventTrigger: {
resource: triggerResource(),
eventType: legacyEventType || provider + "." + eventType,
service,
},
};
if (!!labels && Object.keys(labels).length) {
trigger.labels = { ...trigger.labels, ...labels };
}
return trigger;
},
});
Object.defineProperty(cloudFunction, "__endpoint", {
get: () => {
if (triggerResource() == null) {
return undefined;
}
const endpoint = {
platform: "gcfv1",
...(0, manifest_1.initV1Endpoint)(options),
...optionsToEndpoint(options),
};
if (options.schedule) {
endpoint.scheduleTrigger = (0, manifest_1.initV1ScheduleTrigger)(options.schedule.schedule, options);
(0, encoding_1.copyIfPresent)(endpoint.scheduleTrigger, options.schedule, "timeZone");
(0, encoding_1.copyIfPresent)(endpoint.scheduleTrigger.retryConfig, options.schedule.retryConfig, "retryCount", "maxDoublings", "maxBackoffDuration", "maxRetryDuration", "minBackoffDuration");
}
else {
endpoint.eventTrigger = {
eventType: legacyEventType || provider + "." + eventType,
eventFilters: {
resource: triggerResource(),
},
retry: !!options.failurePolicy,
};
}
// Note: We intentionally don't make use of labels args here.
// labels is used to pass SDK-defined labels to the trigger, which isn't
// something we will do in the container contract world.
endpoint.labels = { ...endpoint.labels };
return endpoint;
},
});
if (options.schedule) {
cloudFunction.__requiredAPIs = [
{
api: "cloudscheduler.googleapis.com",
reason: "Needed for scheduled functions.",
},
];
}
cloudFunction.run = handler || contextOnlyHandler;
return cloudFunction;
}
exports.makeCloudFunction = makeCloudFunction;
function _makeParams(context, triggerResourceGetter) {
var _a, _b, _c;
if (context.params) {
// In unit testing, user may directly provide `context.params`.
return context.params;
}
if (!context.resource) {
// In unit testing, `resource` may be unpopulated for a test event.
return {};
}
const triggerResource = triggerResourceGetter();
const wildcards = triggerResource.match(WILDCARD_REGEX);
const params = {};
// Note: some tests don't set context.resource.name
const eventResourceParts = (_c = (_b = (_a = context === null || context === void 0 ? void 0 : context.resource) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.split) === null || _c === void 0 ? void 0 : _c.call(_b, "/");
if (wildcards && eventResourceParts) {
const triggerResourceParts = triggerResource.split("/");
for (const wildcard of wildcards) {
const wildcardNoBraces = wildcard.slice(1, -1);
const position = triggerResourceParts.indexOf(wildcard);
params[wildcardNoBraces] = eventResourceParts[position];
}
}
return params;
}
function _makeAuth(event, authType) {
var _a, _b, _c, _d, _e, _f;
if (authType === "UNAUTHENTICATED") {
return null;
}
return {
uid: (_c = (_b = (_a = event.context) === null || _a === void 0 ? void 0 : _a.auth) === null || _b === void 0 ? void 0 : _b.variable) === null || _c === void 0 ? void 0 : _c.uid,
token: (_f = (_e = (_d = event.context) === null || _d === void 0 ? void 0 : _d.auth) === null || _e === void 0 ? void 0 : _e.variable) === null || _f === void 0 ? void 0 : _f.token,
};
}
function _detectAuthType(event) {
var _a, _b, _c, _d;
if ((_b = (_a = event.context) === null || _a === void 0 ? void 0 : _a.auth) === null || _b === void 0 ? void 0 : _b.admin) {
return "ADMIN";
}
if ((_d = (_c = event.context) === null || _c === void 0 ? void 0 : _c.auth) === null || _d === void 0 ? void 0 : _d.variable) {
return "USER";
}
return "UNAUTHENTICATED";
}
/** @hidden */
function optionsToTrigger(options) {
const trigger = {};
(0, encoding_1.copyIfPresent)(trigger, options, "regions", "schedule", "minInstances", "maxInstances", "ingressSettings", "vpcConnectorEgressSettings", "vpcConnector", "labels", "secrets");
(0, encoding_1.convertIfPresent)(trigger, options, "failurePolicy", "failurePolicy", (policy) => {
if (policy === false) {
return undefined;
}
else if (policy === true) {
return function_configuration_1.DEFAULT_FAILURE_POLICY;
}
else {
return policy;
}
});
(0, encoding_1.convertIfPresent)(trigger, options, "timeout", "timeoutSeconds", encoding_1.durationFromSeconds);
(0, encoding_1.convertIfPresent)(trigger, options, "availableMemoryMb", "memory", (mem) => {
const memoryLookup = {
"128MB": 128,
"256MB": 256,
"512MB": 512,
"1GB": 1024,
"2GB": 2048,
"4GB": 4096,
"8GB": 8192,
};
return memoryLookup[mem];
});
(0, encoding_1.convertIfPresent)(trigger, options, "serviceAccountEmail", "serviceAccount", encoding_1.serviceAccountFromShorthand);
return trigger;
}
exports.optionsToTrigger = optionsToTrigger;
function optionsToEndpoint(options) {
const endpoint = {};
(0, encoding_1.copyIfPresent)(endpoint, options, "omit", "minInstances", "maxInstances", "ingressSettings", "labels", "timeoutSeconds");
(0, encoding_1.convertIfPresent)(endpoint, options, "region", "regions");
(0, encoding_1.convertIfPresent)(endpoint, options, "serviceAccountEmail", "serviceAccount", (sa) => sa);
(0, encoding_1.convertIfPresent)(endpoint, options, "secretEnvironmentVariables", "secrets", (secrets) => secrets.map((secret) => ({ key: secret instanceof types_1.SecretParam ? secret.name : secret })));
if ((options === null || options === void 0 ? void 0 : options.vpcConnector) !== undefined) {
if (options.vpcConnector === null || options.vpcConnector instanceof options_1.ResetValue) {
endpoint.vpc = function_configuration_1.RESET_VALUE;
}
else {
const vpc = { connector: options.vpcConnector };
(0, encoding_1.convertIfPresent)(vpc, options, "egressSettings", "vpcConnectorEgressSettings");
endpoint.vpc = vpc;
}
}
(0, encoding_1.convertIfPresent)(endpoint, options, "availableMemoryMb", "memory", (mem) => {
const memoryLookup = {
"128MB": 128,
"256MB": 256,
"512MB": 512,
"1GB": 1024,
"2GB": 2048,
"4GB": 4096,
"8GB": 8192,
};
return typeof mem === "object" ? mem : memoryLookup[mem];
});
return endpoint;
}
exports.optionsToEndpoint = optionsToEndpoint;

10
node_modules/firebase-functions/lib/v1/config.d.ts generated vendored Normal file
View File

@@ -0,0 +1,10 @@
export { firebaseConfig } from "../common/config";
/**
* Store and retrieve project configuration data such as third-party API
* keys or other settings. You can set configuration values using the
* Firebase CLI as described in
* https://firebase.google.com/docs/functions/config-env.
*
* @deprecated Using functions.config() is discouraged. See https://firebase.google.com/docs/functions/config-env.
*/
export declare function config(): Record<string, any>;

77
node_modules/firebase-functions/lib/v1/config.js generated vendored Normal file
View File

@@ -0,0 +1,77 @@
"use strict";
// The MIT License (MIT)
//
// Copyright (c) 2017 Firebase
//
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.config = exports.resetCache = exports.singleton = exports.firebaseConfig = void 0;
const fs = require("fs");
const path = require("path");
var config_1 = require("../common/config");
Object.defineProperty(exports, "firebaseConfig", { enumerable: true, get: function () { return config_1.firebaseConfig; } });
/** @internal */
function resetCache() {
exports.singleton = undefined;
}
exports.resetCache = resetCache;
/**
* Store and retrieve project configuration data such as third-party API
* keys or other settings. You can set configuration values using the
* Firebase CLI as described in
* https://firebase.google.com/docs/functions/config-env.
*
* @deprecated Using functions.config() is discouraged. See https://firebase.google.com/docs/functions/config-env.
*/
function config() {
// K_CONFIGURATION is only set in GCFv2
if (process.env.K_CONFIGURATION) {
throw new Error("functions.config() is no longer available in Cloud Functions for " +
"Firebase v2. Please see the latest documentation for information " +
"on how to transition to using environment variables");
}
if (typeof exports.singleton === "undefined") {
init();
}
return exports.singleton;
}
exports.config = config;
function init() {
try {
const parsed = JSON.parse(process.env.CLOUD_RUNTIME_CONFIG);
delete parsed.firebase;
exports.singleton = parsed;
return;
}
catch (e) {
// Do nothing
}
try {
const configPath = process.env.CLOUD_RUNTIME_CONFIG || path.join(process.cwd(), ".runtimeconfig.json");
const contents = fs.readFileSync(configPath);
const parsed = JSON.parse(contents.toString("utf8"));
delete parsed.firebase;
exports.singleton = parsed;
return;
}
catch (e) {
// Do nothing
}
exports.singleton = {};
}

View File

@@ -0,0 +1,191 @@
import * as express from "express";
import { ResetValue } from "../common/options";
import { Expression } from "../params/types";
import { EventContext } from "./cloud-functions";
import { DeploymentOptions, RuntimeOptions, SUPPORTED_REGIONS } from "./function-configuration";
import * as analytics from "./providers/analytics";
import * as auth from "./providers/auth";
import * as database from "./providers/database";
import * as firestore from "./providers/firestore";
import * as https from "./providers/https";
import * as pubsub from "./providers/pubsub";
import * as remoteConfig from "./providers/remoteConfig";
import * as storage from "./providers/storage";
import * as tasks from "./providers/tasks";
import * as testLab from "./providers/testLab";
/**
* Configure the regions that the function is deployed to.
* @param regions One of more region strings.
* @example
* functions.region('us-east1')
* @example
* functions.region('us-east1', 'us-central1')
*/
export declare function region(...regions: Array<(typeof SUPPORTED_REGIONS)[number] | string | Expression<string> | ResetValue>): FunctionBuilder;
/**
* Configure runtime options for the function.
* @param runtimeOptions Object with optional fields:
* 1. `memory`: amount of memory to allocate to the function, possible values
* are: '128MB', '256MB', '512MB', '1GB', '2GB', '4GB', and '8GB'.
* 2. `timeoutSeconds`: timeout for the function in seconds, possible values are
* 0 to 540.
* 3. `failurePolicy`: failure policy of the function, with boolean `true` being
* equivalent to providing an empty retry object.
* 4. `vpcConnector`: id of a VPC connector in same project and region.
* 5. `vpcConnectorEgressSettings`: when a vpcConnector is set, control which
* egress traffic is sent through the vpcConnector.
* 6. `serviceAccount`: Specific service account for the function.
* 7. `ingressSettings`: ingress settings for the function, which control where a HTTPS
* function can be called from.
*
* Value must not be null.
*/
export declare function runWith(runtimeOptions: RuntimeOptions): FunctionBuilder;
export declare class FunctionBuilder {
private options;
constructor(options: DeploymentOptions);
/**
* Configure the regions that the function is deployed to.
* @param regions One or more region strings.
* @example
* functions.region('us-east1')
* @example
* functions.region('us-east1', 'us-central1')
*/
region(...regions: Array<(typeof SUPPORTED_REGIONS)[number] | string | Expression<string> | ResetValue>): FunctionBuilder;
/**
* Configure runtime options for the function.
* @param runtimeOptions Object with optional fields:
* 1. `memory`: amount of memory to allocate to the function, possible values
* are: '128MB', '256MB', '512MB', '1GB', '2GB', '4GB', and '8GB'.
* 2. `timeoutSeconds`: timeout for the function in seconds, possible values are
* 0 to 540.
* 3. `failurePolicy`: failure policy of the function, with boolean `true` being
* equivalent to providing an empty retry object.
* 4. `vpcConnector`: id of a VPC connector in the same project and region
* 5. `vpcConnectorEgressSettings`: when a `vpcConnector` is set, control which
* egress traffic is sent through the `vpcConnector`.
*
* Value must not be null.
*/
runWith(runtimeOptions: RuntimeOptions): FunctionBuilder;
get https(): {
/**
* Handle HTTP requests.
* @param handler A function that takes a request and response object,
* same signature as an Express app.
*/
onRequest: (handler: (req: https.Request, resp: express.Response) => void | Promise<void>) => import("./cloud-functions").HttpsFunction;
/**
* Declares a callable method for clients to call using a Firebase SDK.
* @param handler A method that takes a data and context and returns a value.
*/
onCall: (handler: (data: any, context: https.CallableContext) => any | Promise<any>) => import("./cloud-functions").HttpsFunction & import("./cloud-functions").Runnable<any>;
};
get tasks(): {
/**
* Declares a task queue function for clients to call using a Firebase Admin SDK.
* @param options Configurations for the task queue function.
*/
/** @hidden */
taskQueue: (options?: tasks.TaskQueueOptions) => tasks.TaskQueueBuilder;
};
get database(): {
/**
* Selects a database instance that will trigger the function. If omitted,
* will pick the default database for your project.
* @param instance The Realtime Database instance to use.
*/
instance: (instance: string) => database.InstanceBuilder;
/**
* Select Firebase Realtime Database Reference to listen to.
*
* This method behaves very similarly to the method of the same name in
* the client and Admin Firebase SDKs. Any change to the Database that
* affects the data at or below the provided `path` will fire an event in
* Cloud Functions.
*
* There are three important differences between listening to a Realtime
* Database event in Cloud Functions and using the Realtime Database in
* the client and Admin SDKs:
* 1. Cloud Functions allows wildcards in the `path` name. Any `path`
* component in curly brackets (`{}`) is a wildcard that matches all
* strings. The value that matched a certain invocation of a Cloud
* Function is returned as part of the `context.params` object. For
* example, `ref("messages/{messageId}")` matches changes at
* `/messages/message1` or `/messages/message2`, resulting in
* `context.params.messageId` being set to `"message1"` or
* `"message2"`, respectively.
* 2. Cloud Functions do not fire an event for data that already existed
* before the Cloud Function was deployed.
* 3. Cloud Function events have access to more information, including
* information about the user who triggered the Cloud Function.
* @param ref Path of the database to listen to.
*/
ref: <Ref extends string>(path: Ref) => database.RefBuilder<Ref>;
};
get firestore(): {
/**
* Select the Firestore document to listen to for events.
* @param path Full database path to listen to. This includes the name of
* the collection that the document is a part of. For example, if the
* collection is named "users" and the document is named "Ada", then the
* path is "/users/Ada".
*/
document: <Path extends string>(path: Path) => firestore.DocumentBuilder<Path>;
/** @hidden */
namespace: (namespace: string) => firestore.NamespaceBuilder;
/** @hidden */
database: (database: string) => firestore.DatabaseBuilder;
};
get analytics(): {
/**
* Select analytics events to listen to for events.
* @param analyticsEventType Name of the analytics event type.
*/
event: (analyticsEventType: string) => analytics.AnalyticsEventBuilder;
};
get remoteConfig(): {
/**
* Handle all updates (including rollbacks) that affect a Remote Config
* project.
* @param handler A function that takes the updated Remote Config template
* version metadata as an argument.
*/
onUpdate: (handler: (version: remoteConfig.TemplateVersion, context: EventContext) => PromiseLike<any> | any) => import("./cloud-functions").CloudFunction<remoteConfig.TemplateVersion>;
};
get storage(): {
/**
* The optional bucket function allows you to choose which buckets' events
* to handle. This step can be bypassed by calling object() directly,
* which will use the default Cloud Storage for Firebase bucket.
* @param bucket Name of the Google Cloud Storage bucket to listen to.
*/
bucket: (bucket?: string) => storage.BucketBuilder;
/**
* Handle events related to Cloud Storage objects.
*/
object: () => storage.ObjectBuilder;
};
get pubsub(): {
/**
* Select Cloud Pub/Sub topic to listen to.
* @param topic Name of Pub/Sub topic, must belong to the same project as
* the function.
*/
topic: (topic: string) => pubsub.TopicBuilder;
schedule: (schedule: string) => pubsub.ScheduleBuilder;
};
get auth(): {
/**
* Handle events related to Firebase authentication users.
*/
user: (userOptions?: auth.UserOptions) => auth.UserBuilder;
};
get testLab(): {
/**
* Handle events related to Test Lab test matrices.
*/
testMatrix: () => testLab.TestMatrixBuilder;
};
}

View File

@@ -0,0 +1,383 @@
"use strict";
// The MIT License (MIT)
//
// Copyright (c) 2017 Firebase
//
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.FunctionBuilder = exports.runWith = exports.region = void 0;
const options_1 = require("../common/options");
const types_1 = require("../params/types");
const function_configuration_1 = require("./function-configuration");
const analytics = require("./providers/analytics");
const auth = require("./providers/auth");
const database = require("./providers/database");
const firestore = require("./providers/firestore");
const https = require("./providers/https");
const pubsub = require("./providers/pubsub");
const remoteConfig = require("./providers/remoteConfig");
const storage = require("./providers/storage");
const tasks = require("./providers/tasks");
const testLab = require("./providers/testLab");
/**
* Assert that the runtime options passed in are valid.
* @param runtimeOptions object containing memory and timeout information.
* @throws { Error } Memory and TimeoutSeconds values must be valid.
*/
function assertRuntimeOptionsValid(runtimeOptions) {
const mem = runtimeOptions.memory;
if (mem && typeof mem !== "object" && !function_configuration_1.VALID_MEMORY_OPTIONS.includes(mem)) {
throw new Error(`The only valid memory allocation values are: ${function_configuration_1.VALID_MEMORY_OPTIONS.join(", ")}`);
}
if (typeof runtimeOptions.timeoutSeconds === "number" &&
(runtimeOptions.timeoutSeconds > function_configuration_1.MAX_TIMEOUT_SECONDS || runtimeOptions.timeoutSeconds < 0)) {
throw new Error(`TimeoutSeconds must be between 0 and ${function_configuration_1.MAX_TIMEOUT_SECONDS}`);
}
if (runtimeOptions.ingressSettings &&
!(runtimeOptions.ingressSettings instanceof options_1.ResetValue) &&
!function_configuration_1.INGRESS_SETTINGS_OPTIONS.includes(runtimeOptions.ingressSettings)) {
throw new Error(`The only valid ingressSettings values are: ${function_configuration_1.INGRESS_SETTINGS_OPTIONS.join(",")}`);
}
if (runtimeOptions.vpcConnectorEgressSettings &&
!(runtimeOptions.vpcConnectorEgressSettings instanceof options_1.ResetValue) &&
!function_configuration_1.VPC_EGRESS_SETTINGS_OPTIONS.includes(runtimeOptions.vpcConnectorEgressSettings)) {
throw new Error(`The only valid vpcConnectorEgressSettings values are: ${function_configuration_1.VPC_EGRESS_SETTINGS_OPTIONS.join(",")}`);
}
validateFailurePolicy(runtimeOptions.failurePolicy);
const serviceAccount = runtimeOptions.serviceAccount;
if (serviceAccount &&
!(serviceAccount === "default" ||
serviceAccount instanceof options_1.ResetValue ||
serviceAccount instanceof types_1.Expression ||
serviceAccount.includes("@"))) {
throw new Error(`serviceAccount must be set to 'default', a string expression, a service account email, or '{serviceAccountName}@'`);
}
if (runtimeOptions.labels) {
// Labels must follow the rules listed in
// https://cloud.google.com/resource-manager/docs/creating-managing-labels#requirements
if (Object.keys(runtimeOptions.labels).length > function_configuration_1.MAX_NUMBER_USER_LABELS) {
throw new Error(`A function must not have more than ${function_configuration_1.MAX_NUMBER_USER_LABELS} user-defined labels.`);
}
// We reserve the 'deployment' and 'firebase' namespaces for future feature development.
const reservedKeys = Object.keys(runtimeOptions.labels).filter((key) => key.startsWith("deployment") || key.startsWith("firebase"));
if (reservedKeys.length) {
throw new Error(`Invalid labels: ${reservedKeys.join(", ")}. Labels may not start with reserved names 'deployment' or 'firebase'`);
}
const invalidLengthKeys = Object.keys(runtimeOptions.labels).filter((key) => key.length < 1 || key.length > 63);
if (invalidLengthKeys.length > 0) {
throw new Error(`Invalid labels: ${invalidLengthKeys.join(", ")}. Label keys must be between 1 and 63 characters in length.`);
}
const invalidLengthValues = Object.values(runtimeOptions.labels).filter((value) => value.length > 63);
if (invalidLengthValues.length > 0) {
throw new Error(`Invalid labels: ${invalidLengthValues.join(", ")}. Label values must be less than 64 charcters.`);
}
// Keys can contain lowercase letters, foreign characters, numbers, _ or -. They must start with a letter.
const validKeyPattern = /^[\p{Ll}\p{Lo}][\p{Ll}\p{Lo}\p{N}_-]{0,62}$/u;
const invalidKeys = Object.keys(runtimeOptions.labels).filter((key) => !validKeyPattern.test(key));
if (invalidKeys.length > 0) {
throw new Error(`Invalid labels: ${invalidKeys.join(", ")}. Label keys can only contain lowercase letters, international characters, numbers, _ or -, and must start with a letter.`);
}
// Values can contain lowercase letters, foreign characters, numbers, _ or -.
const validValuePattern = /^[\p{Ll}\p{Lo}\p{N}_-]{0,63}$/u;
const invalidValues = Object.values(runtimeOptions.labels).filter((value) => !validValuePattern.test(value));
if (invalidValues.length > 0) {
throw new Error(`Invalid labels: ${invalidValues.join(", ")}. Label values can only contain lowercase letters, international characters, numbers, _ or -.`);
}
}
if (typeof runtimeOptions.invoker === "string" && runtimeOptions.invoker.length === 0) {
throw new Error("Invalid service account for function invoker, must be a non-empty string");
}
if (runtimeOptions.invoker !== undefined && Array.isArray(runtimeOptions.invoker)) {
if (runtimeOptions.invoker.length === 0) {
throw new Error("Invalid invoker array, must contain at least 1 service account entry");
}
for (const serviceAccount of runtimeOptions.invoker) {
if (serviceAccount.length === 0) {
throw new Error("Invalid invoker array, a service account must be a non-empty string");
}
if (serviceAccount === "public") {
throw new Error("Invalid invoker array, a service account cannot be set to the 'public' identifier");
}
if (serviceAccount === "private") {
throw new Error("Invalid invoker array, a service account cannot be set to the 'private' identifier");
}
}
}
if (runtimeOptions.secrets !== undefined) {
const invalidSecrets = runtimeOptions.secrets.filter((s) => !/^[A-Za-z\d\-_]+$/.test(s instanceof types_1.SecretParam ? s.name : s));
if (invalidSecrets.length > 0) {
throw new Error(`Invalid secrets: ${invalidSecrets.join(",")}. ` +
"Secret must be configured using the resource id (e.g. API_KEY)");
}
}
if ("allowInvalidAppCheckToken" in runtimeOptions) {
throw new Error('runWith option "allowInvalidAppCheckToken" has been inverted and ' +
'renamed "enforceAppCheck"');
}
return true;
}
function validateFailurePolicy(policy) {
if (typeof policy === "boolean" || typeof policy === "undefined") {
return;
}
if (typeof policy !== "object") {
throw new Error(`failurePolicy must be a boolean or an object.`);
}
const retry = policy.retry;
if (typeof retry !== "object" || Object.keys(retry).length) {
throw new Error("failurePolicy.retry must be an empty object.");
}
}
/**
* Assert regions specified are valid.
* @param regions list of regions.
* @throws { Error } Regions must be in list of supported regions.
*/
function assertRegionsAreValid(regions) {
if (!regions.length) {
throw new Error("You must specify at least one region");
}
return true;
}
/**
* Configure the regions that the function is deployed to.
* @param regions One of more region strings.
* @example
* functions.region('us-east1')
* @example
* functions.region('us-east1', 'us-central1')
*/
function region(...regions) {
if (assertRegionsAreValid(regions)) {
return new FunctionBuilder({ regions });
}
}
exports.region = region;
/**
* Configure runtime options for the function.
* @param runtimeOptions Object with optional fields:
* 1. `memory`: amount of memory to allocate to the function, possible values
* are: '128MB', '256MB', '512MB', '1GB', '2GB', '4GB', and '8GB'.
* 2. `timeoutSeconds`: timeout for the function in seconds, possible values are
* 0 to 540.
* 3. `failurePolicy`: failure policy of the function, with boolean `true` being
* equivalent to providing an empty retry object.
* 4. `vpcConnector`: id of a VPC connector in same project and region.
* 5. `vpcConnectorEgressSettings`: when a vpcConnector is set, control which
* egress traffic is sent through the vpcConnector.
* 6. `serviceAccount`: Specific service account for the function.
* 7. `ingressSettings`: ingress settings for the function, which control where a HTTPS
* function can be called from.
*
* Value must not be null.
*/
function runWith(runtimeOptions) {
if (assertRuntimeOptionsValid(runtimeOptions)) {
return new FunctionBuilder(runtimeOptions);
}
}
exports.runWith = runWith;
class FunctionBuilder {
constructor(options) {
this.options = options;
}
/**
* Configure the regions that the function is deployed to.
* @param regions One or more region strings.
* @example
* functions.region('us-east1')
* @example
* functions.region('us-east1', 'us-central1')
*/
region(...regions) {
if (assertRegionsAreValid(regions)) {
this.options.regions = regions;
return this;
}
}
/**
* Configure runtime options for the function.
* @param runtimeOptions Object with optional fields:
* 1. `memory`: amount of memory to allocate to the function, possible values
* are: '128MB', '256MB', '512MB', '1GB', '2GB', '4GB', and '8GB'.
* 2. `timeoutSeconds`: timeout for the function in seconds, possible values are
* 0 to 540.
* 3. `failurePolicy`: failure policy of the function, with boolean `true` being
* equivalent to providing an empty retry object.
* 4. `vpcConnector`: id of a VPC connector in the same project and region
* 5. `vpcConnectorEgressSettings`: when a `vpcConnector` is set, control which
* egress traffic is sent through the `vpcConnector`.
*
* Value must not be null.
*/
runWith(runtimeOptions) {
if (assertRuntimeOptionsValid(runtimeOptions)) {
this.options = {
...this.options,
...runtimeOptions,
};
return this;
}
}
get https() {
if (this.options.failurePolicy !== undefined) {
console.warn("RuntimeOptions.failurePolicy is not supported in https functions.");
}
return {
/**
* Handle HTTP requests.
* @param handler A function that takes a request and response object,
* same signature as an Express app.
*/
onRequest: (handler) => https._onRequestWithOptions(handler, this.options),
/**
* Declares a callable method for clients to call using a Firebase SDK.
* @param handler A method that takes a data and context and returns a value.
*/
onCall: (handler) => https._onCallWithOptions(handler, this.options),
};
}
get tasks() {
return {
/**
* Declares a task queue function for clients to call using a Firebase Admin SDK.
* @param options Configurations for the task queue function.
*/
/** @hidden */
taskQueue: (options) => {
return new tasks.TaskQueueBuilder(options, this.options);
},
};
}
get database() {
return {
/**
* Selects a database instance that will trigger the function. If omitted,
* will pick the default database for your project.
* @param instance The Realtime Database instance to use.
*/
instance: (instance) => database._instanceWithOptions(instance, this.options),
/**
* Select Firebase Realtime Database Reference to listen to.
*
* This method behaves very similarly to the method of the same name in
* the client and Admin Firebase SDKs. Any change to the Database that
* affects the data at or below the provided `path` will fire an event in
* Cloud Functions.
*
* There are three important differences between listening to a Realtime
* Database event in Cloud Functions and using the Realtime Database in
* the client and Admin SDKs:
* 1. Cloud Functions allows wildcards in the `path` name. Any `path`
* component in curly brackets (`{}`) is a wildcard that matches all
* strings. The value that matched a certain invocation of a Cloud
* Function is returned as part of the `context.params` object. For
* example, `ref("messages/{messageId}")` matches changes at
* `/messages/message1` or `/messages/message2`, resulting in
* `context.params.messageId` being set to `"message1"` or
* `"message2"`, respectively.
* 2. Cloud Functions do not fire an event for data that already existed
* before the Cloud Function was deployed.
* 3. Cloud Function events have access to more information, including
* information about the user who triggered the Cloud Function.
* @param ref Path of the database to listen to.
*/
ref: (path) => database._refWithOptions(path, this.options),
};
}
get firestore() {
return {
/**
* Select the Firestore document to listen to for events.
* @param path Full database path to listen to. This includes the name of
* the collection that the document is a part of. For example, if the
* collection is named "users" and the document is named "Ada", then the
* path is "/users/Ada".
*/
document: (path) => firestore._documentWithOptions(path, this.options),
/** @hidden */
namespace: (namespace) => firestore._namespaceWithOptions(namespace, this.options),
/** @hidden */
database: (database) => firestore._databaseWithOptions(database, this.options),
};
}
get analytics() {
return {
/**
* Select analytics events to listen to for events.
* @param analyticsEventType Name of the analytics event type.
*/
event: (analyticsEventType) => analytics._eventWithOptions(analyticsEventType, this.options),
};
}
get remoteConfig() {
return {
/**
* Handle all updates (including rollbacks) that affect a Remote Config
* project.
* @param handler A function that takes the updated Remote Config template
* version metadata as an argument.
*/
onUpdate: (handler) => remoteConfig._onUpdateWithOptions(handler, this.options),
};
}
get storage() {
return {
/**
* The optional bucket function allows you to choose which buckets' events
* to handle. This step can be bypassed by calling object() directly,
* which will use the default Cloud Storage for Firebase bucket.
* @param bucket Name of the Google Cloud Storage bucket to listen to.
*/
bucket: (bucket) => storage._bucketWithOptions(this.options, bucket),
/**
* Handle events related to Cloud Storage objects.
*/
object: () => storage._objectWithOptions(this.options),
};
}
get pubsub() {
return {
/**
* Select Cloud Pub/Sub topic to listen to.
* @param topic Name of Pub/Sub topic, must belong to the same project as
* the function.
*/
topic: (topic) => pubsub._topicWithOptions(topic, this.options),
schedule: (schedule) => pubsub._scheduleWithOptions(schedule, this.options),
};
}
get auth() {
return {
/**
* Handle events related to Firebase authentication users.
*/
user: (userOptions) => auth._userWithOptions(this.options, userOptions),
};
}
get testLab() {
return {
/**
* Handle events related to Test Lab test matrices.
*/
testMatrix: () => testLab._testMatrixWithOpts(this.options),
};
}
}
exports.FunctionBuilder = FunctionBuilder;

View File

@@ -0,0 +1,226 @@
import { Expression } from "../params";
import { ResetValue } from "../common/options";
import { SecretParam } from "../params/types";
export { RESET_VALUE } from "../common/options";
/**
* List of all regions supported by Cloud Functions.
*/
export declare const SUPPORTED_REGIONS: readonly ["us-central1", "us-east1", "us-east4", "us-west2", "us-west3", "us-west4", "europe-central2", "europe-west1", "europe-west2", "europe-west3", "europe-west6", "asia-east1", "asia-east2", "asia-northeast1", "asia-northeast2", "asia-northeast3", "asia-south1", "asia-southeast1", "asia-southeast2", "northamerica-northeast1", "southamerica-east1", "australia-southeast1"];
/**
* Cloud Functions min timeout value.
*/
export declare const MIN_TIMEOUT_SECONDS = 0;
/**
* Cloud Functions max timeout value.
*/
export declare const MAX_TIMEOUT_SECONDS = 540;
/**
* List of available memory options supported by Cloud Functions.
*/
export declare const VALID_MEMORY_OPTIONS: readonly ["128MB", "256MB", "512MB", "1GB", "2GB", "4GB", "8GB"];
/**
* List of available options for VpcConnectorEgressSettings.
*/
export declare const VPC_EGRESS_SETTINGS_OPTIONS: readonly ["VPC_CONNECTOR_EGRESS_SETTINGS_UNSPECIFIED", "PRIVATE_RANGES_ONLY", "ALL_TRAFFIC"];
/**
* List of available options for IngressSettings.
*/
export declare const INGRESS_SETTINGS_OPTIONS: readonly ["INGRESS_SETTINGS_UNSPECIFIED", "ALLOW_ALL", "ALLOW_INTERNAL_ONLY", "ALLOW_INTERNAL_AND_GCLB"];
/**
* Scheduler retry options. Applies only to scheduled functions.
*/
export interface ScheduleRetryConfig {
/**
* The number of attempts that the system will make to run a job using the exponential backoff procedure described by {@link ScheduleRetryConfig.maxDoublings}.
*
* @defaultValue 0 (infinite retry)
*/
retryCount?: number | Expression<number> | ResetValue;
/**
* The time limit for retrying a failed job, measured from time when an execution was first attempted.
*
* If specified with {@link ScheduleRetryConfig.retryCount}, the job will be retried until both limits are reached.
*
* @defaultValue 0
*/
maxRetryDuration?: string | Expression<string> | ResetValue;
/**
* The minimum amount of time to wait before retrying a job after it fails.
*
* @defaultValue 5 seconds
*/
minBackoffDuration?: string | Expression<string> | ResetValue;
/**
* The maximum amount of time to wait before retrying a job after it fails.
*
* @defaultValue 1 hour
*/
maxBackoffDuration?: string | Expression<string> | ResetValue;
/**
* The max number of backoff doubling applied at each retry.
*
* @defaultValue 5
*/
maxDoublings?: number | Expression<number> | ResetValue;
}
/**
* Configuration options for scheduled functions.
*/
export interface Schedule {
/**
* Describes the schedule on which the job will be executed.
*
* The schedule can be either of the following types:
*
* 1. {@link https://en.wikipedia.org/wiki/Cron#Overview | Crontab}
*
* 2. English-like {@link https://cloud.google.com/scheduler/docs/configuring/cron-job-schedules | schedule}
*
* @example
* ```
* // Crontab schedule
* schedule: "0 9 * * 1"` // Every Monday at 09:00 AM
*
* // English-like schedule
* schedule: "every 5 minutes"
* ```
*/
schedule: string;
/**
* Specifies the time zone to be used in interpreting {@link Schedule.schedule}.
*
* The value of this field must be a time zone name from the tz database.
*/
timeZone?: string | ResetValue;
/**
* Settings that determine the retry behavior.
*/
retryConfig?: ScheduleRetryConfig;
}
/**
* Configuration option for failure policy on background functions.
*/
export interface FailurePolicy {
/**
* Retry configuration. Must be an empty object.
*
*/
retry: Record<string, never>;
}
export declare const DEFAULT_FAILURE_POLICY: FailurePolicy;
export declare const MAX_NUMBER_USER_LABELS = 58;
/**
* Configuration options for a function that applicable at runtime.
*/
export interface RuntimeOptions {
/**
* Failure policy of the function, with boolean `true` being equivalent to
* providing an empty retry object.
*/
failurePolicy?: FailurePolicy | boolean;
/**
* Amount of memory to allocate to the function.
*/
memory?: (typeof VALID_MEMORY_OPTIONS)[number] | Expression<number> | ResetValue;
/**
* Timeout for the function in seconds, possible values are 0 to 540.
*/
timeoutSeconds?: number | Expression<number> | ResetValue;
/**
* Min number of actual instances to be running at a given time.
*
* @remarks
* Instances will be billed for memory allocation and 10% of CPU allocation
* while idle.
*/
minInstances?: number | Expression<number> | ResetValue;
/**
* Max number of actual instances allowed to be running in parallel.
*/
maxInstances?: number | Expression<number> | ResetValue;
/**
* Connect cloud function to specified VPC connector.
*/
vpcConnector?: string | Expression<string> | ResetValue;
/**
* Egress settings for VPC connector.
*/
vpcConnectorEgressSettings?: (typeof VPC_EGRESS_SETTINGS_OPTIONS)[number] | ResetValue;
/**
* Specific service account for the function to run as.
*/
serviceAccount?: "default" | string | Expression<string> | ResetValue;
/**
* Ingress settings which control where this function can be called from.
*/
ingressSettings?: (typeof INGRESS_SETTINGS_OPTIONS)[number] | ResetValue;
/**
* User labels to set on the function.
*/
labels?: Record<string, string>;
/**
* Invoker to set access control on https functions.
*/
invoker?: "public" | "private" | string | string[];
secrets?: (string | SecretParam)[];
/**
* Determines whether Firebase AppCheck is enforced.
*
* @remarks
* When true, requests with invalid tokens autorespond with a 401
* (Unauthorized) error.
* When false, requests with invalid tokens set context.app to undefiend.
*/
enforceAppCheck?: boolean;
/**
* Determines whether Firebase App Check token is consumed on request. Defaults to false.
*
* @remarks
* Set this to true to enable the App Check replay protection feature by consuming the App Check token on callable
* request. Tokens that are found to be already consumed will have the `request.app.alreadyConsumed` property set
* to true.
*
*
* Tokens are only considered to be consumed if it is sent to the App Check service by setting this option to true.
* Other uses of the token do not consume it.
*
* This replay protection feature requires an additional network call to the App Check backend and forces the clients
* to obtain a fresh attestation from the chosen attestation providers. This can therefore negatively impact
* performance and can potentially deplete your attestation providers' quotas faster. Use this feature only for
* protecting low volume, security critical, or expensive operations.
*
* This option does not affect the `enforceAppCheck` option. Setting the latter to true will cause the callable function
* to automatically respond with a 401 Unauthorized status code when the request includes an invalid App Check token.
* When the request includes valid but consumed App Check tokens, requests will not be automatically rejected. Instead,
* the `request.app.alreadyConsumed` property will be set to true and pass the execution to the handler code for making
* further decisions, such as requiring additional security checks or rejecting the request.
*/
consumeAppCheckToken?: boolean;
/**
* Controls whether function configuration modified outside of function source is preserved. Defaults to false.
*
* @remarks
* When setting configuration available in the underlying platform that is not yet available in the Firebase Functions
* SDK, we highly recommend setting `preserveExternalChanges` to `true`. Otherwise, when the Firebase Functions SDK releases
* a new version of the SDK with support for the missing configuration, your function's manually configured setting
* may inadvertently be wiped out.
*/
preserveExternalChanges?: boolean;
}
/**
* Configuration options for a function that applies during function deployment.
*/
export interface DeploymentOptions extends RuntimeOptions {
/**
* If true, do not deploy or emulate this function.
*/
omit?: boolean | Expression<boolean>;
/**
* Regions where function should be deployed.
*/
regions?: Array<(typeof SUPPORTED_REGIONS)[number] | string | Expression<string> | ResetValue>;
/**
* Schedule for the scheduled function.
*/
schedule?: Schedule;
}

View File

@@ -0,0 +1,73 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MAX_NUMBER_USER_LABELS = exports.DEFAULT_FAILURE_POLICY = exports.INGRESS_SETTINGS_OPTIONS = exports.VPC_EGRESS_SETTINGS_OPTIONS = exports.VALID_MEMORY_OPTIONS = exports.MAX_TIMEOUT_SECONDS = exports.MIN_TIMEOUT_SECONDS = exports.SUPPORTED_REGIONS = exports.RESET_VALUE = void 0;
var options_1 = require("../common/options");
Object.defineProperty(exports, "RESET_VALUE", { enumerable: true, get: function () { return options_1.RESET_VALUE; } });
/**
* List of all regions supported by Cloud Functions.
*/
exports.SUPPORTED_REGIONS = [
"us-central1",
"us-east1",
"us-east4",
"us-west2",
"us-west3",
"us-west4",
"europe-central2",
"europe-west1",
"europe-west2",
"europe-west3",
"europe-west6",
"asia-east1",
"asia-east2",
"asia-northeast1",
"asia-northeast2",
"asia-northeast3",
"asia-south1",
"asia-southeast1",
"asia-southeast2",
"northamerica-northeast1",
"southamerica-east1",
"australia-southeast1",
];
/**
* Cloud Functions min timeout value.
*/
exports.MIN_TIMEOUT_SECONDS = 0;
/**
* Cloud Functions max timeout value.
*/
exports.MAX_TIMEOUT_SECONDS = 540;
/**
* List of available memory options supported by Cloud Functions.
*/
exports.VALID_MEMORY_OPTIONS = [
"128MB",
"256MB",
"512MB",
"1GB",
"2GB",
"4GB",
"8GB",
];
/**
* List of available options for VpcConnectorEgressSettings.
*/
exports.VPC_EGRESS_SETTINGS_OPTIONS = [
"VPC_CONNECTOR_EGRESS_SETTINGS_UNSPECIFIED",
"PRIVATE_RANGES_ONLY",
"ALL_TRAFFIC",
];
/**
* List of available options for IngressSettings.
*/
exports.INGRESS_SETTINGS_OPTIONS = [
"INGRESS_SETTINGS_UNSPECIFIED",
"ALLOW_ALL",
"ALLOW_INTERNAL_ONLY",
"ALLOW_INTERNAL_AND_GCLB",
];
exports.DEFAULT_FAILURE_POLICY = {
retry: {},
};
exports.MAX_NUMBER_USER_LABELS = 58;

23
node_modules/firebase-functions/lib/v1/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,23 @@
import * as logger from "../logger";
import * as analytics from "./providers/analytics";
import * as auth from "./providers/auth";
import * as database from "./providers/database";
import * as firestore from "./providers/firestore";
import * as https from "./providers/https";
import * as pubsub from "./providers/pubsub";
import * as remoteConfig from "./providers/remoteConfig";
import * as storage from "./providers/storage";
import * as tasks from "./providers/tasks";
import * as testLab from "./providers/testLab";
import { setApp as setEmulatedAdminApp } from "../common/app";
export { analytics, auth, database, firestore, https, pubsub, remoteConfig, storage, tasks, testLab, logger, };
export declare const app: {
setEmulatedAdminApp: typeof setEmulatedAdminApp;
};
export * from "./cloud-functions";
export * from "./config";
export * from "./function-builder";
export * from "./function-configuration";
import * as params from "../params";
export { params };
export { onInit } from "../common/onInit";

73
node_modules/firebase-functions/lib/v1/index.js generated vendored Normal file
View File

@@ -0,0 +1,73 @@
"use strict";
// The MIT License (MIT)
//
// Copyright (c) 2017 Firebase
//
// 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.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.onInit = exports.params = exports.app = exports.logger = exports.testLab = exports.tasks = exports.storage = exports.remoteConfig = exports.pubsub = exports.https = exports.firestore = exports.database = exports.auth = exports.analytics = void 0;
// Providers:
const logger = require("../logger");
exports.logger = logger;
const analytics = require("./providers/analytics");
exports.analytics = analytics;
const auth = require("./providers/auth");
exports.auth = auth;
const database = require("./providers/database");
exports.database = database;
const firestore = require("./providers/firestore");
exports.firestore = firestore;
const https = require("./providers/https");
exports.https = https;
const pubsub = require("./providers/pubsub");
exports.pubsub = pubsub;
const remoteConfig = require("./providers/remoteConfig");
exports.remoteConfig = remoteConfig;
const storage = require("./providers/storage");
exports.storage = storage;
const tasks = require("./providers/tasks");
exports.tasks = tasks;
const testLab = require("./providers/testLab");
exports.testLab = testLab;
const app_1 = require("../common/app");
exports.app = { setEmulatedAdminApp: app_1.setApp };
// Exported root types:
__exportStar(require("./cloud-functions"), exports);
__exportStar(require("./config"), exports);
__exportStar(require("./function-builder"), exports);
__exportStar(require("./function-configuration"), exports);
// NOTE: Equivalent to `export * as params from "../params"` but api-extractor doesn't support that syntax.
const params = require("../params");
exports.params = params;
var onInit_1 = require("../common/onInit");
Object.defineProperty(exports, "onInit", { enumerable: true, get: function () { return onInit_1.onInit; } });

View File

@@ -0,0 +1,241 @@
import { CloudFunction, EventContext } from "../cloud-functions";
import { DeploymentOptions } from "../function-configuration";
/**
* Registers a function to handle analytics events.
*
* @param analyticsEventType Name of the analytics event type to which
* this Cloud Function is scoped.
*
* @returns Analytics event builder interface.
*/
export declare function event(analyticsEventType: string): AnalyticsEventBuilder;
/**
* The Firebase Analytics event builder interface.
*
* Access via `functions.analytics.event()`.
*/
export declare class AnalyticsEventBuilder {
private triggerResource;
private options;
/** @hidden */
constructor(triggerResource: () => string, options: DeploymentOptions);
/**
* Event handler that fires every time a Firebase Analytics event occurs.
*
* @param handler Event handler that fires every time a Firebase Analytics event
* occurs.
*
* @returns A function that you can export and deploy.
*/
onLog(handler: (event: AnalyticsEvent, context: EventContext) => PromiseLike<any> | any): CloudFunction<AnalyticsEvent>;
}
/** Interface representing a Firebase Analytics event that was logged for a specific user. */
export declare class AnalyticsEvent {
/**
* The date on which the event.was logged.
* (`YYYYMMDD` format in the registered timezone of your app).
*/
reportingDate: string;
/** The name of the event. */
name: string;
/**
* A map of parameters and their values associated with the event.
*
* Note: Values in this map are cast to the most appropriate type. Due to
* the nature of JavaScript's number handling, this might entail a loss of
* precision in cases of very large integers.
*/
params: {
[key: string]: any;
};
/** UTC client time when the event happened. */
logTime: string;
/** UTC client time when the previous event happened. */
previousLogTime?: string;
/** Value parameter in USD. */
valueInUSD?: number;
/** User-related dimensions. */
user?: UserDimensions;
/** @hidden */
constructor(wireFormat: any);
}
/**
* Interface representing the user who triggered the events.
*/
export declare class UserDimensions {
/**
* The user ID set via the `setUserId` API.
* [Android](https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.html#setUserId(java.lang.String))
* [iOS](https://firebase.google.com/docs/reference/ios/firebaseanalytics/api/reference/Classes/FIRAnalytics#/c:objc(cs)FIRAnalytics(cm)setUserID)
*/
userId?: string;
/** The time (in UTC) at which the user first opened the app. */
firstOpenTime?: string;
/**
* A map of user properties set with the
* [`setUserProperty`](https://firebase.google.com/docs/analytics/android/properties) API.
*
* All values are [`UserPropertyValue`](providers_analytics_.userpropertyvalue) objects.
*/
userProperties: {
[key: string]: UserPropertyValue;
};
/** Device information. */
deviceInfo: DeviceInfo;
/** User's geographic information. */
geoInfo: GeoInfo;
/** App information. */
appInfo?: AppInfo;
/** Information regarding the bundle in which these events were uploaded. */
bundleInfo: ExportBundleInfo;
/** @hidden */
constructor(wireFormat: any);
}
/** Predefined or custom properties stored on the client side. */
export declare class UserPropertyValue {
/** The last set value of a user property. */
value: string;
/** UTC client time when the user property was last set. */
setTime: string;
/** @hidden */
constructor(wireFormat: any);
}
/**
* Interface representing the device that triggered these
* Firebase Analytics events.
*/
export interface DeviceInfo {
/**
* Device category.
*
* Examples: "tablet" or "mobile".
*/
deviceCategory?: string;
/**
* Device brand name.
*
* Examples: "Samsung", "HTC"
*/
mobileBrandName?: string;
/**
* Device model name in human-readable format.
*
* Example: "iPhone 7"
*/
mobileModelName?: string;
/**
* Device marketing name.
*
* Example: "Galaxy S4 Mini"
*/
mobileMarketingName?: string;
/**
* Device model, as read from the OS.
*
* Example: "iPhone9,1"
*/
deviceModel?: string;
/**
* Device OS version when data capture ended.
*
* Example: "4.4.2"
*/
platformVersion?: string;
/**
* Vendor specific device identifier. This is IDFV on iOS. Not used for Android.
*
* Example: '599F9C00-92DC-4B5C-9464-7971F01F8370'
*/
deviceId?: string;
/**
* The type of the [`resettable_device_id`](https://support.google.com/dfp_premium/answer/6238701?hl=en)
* is IDFA on iOS (when available) and AdId on Android.
*
* Example: "71683BF9-FA3B-4B0D-9535-A1F05188BAF3"
*/
resettableDeviceId?: string;
/**
* The user language in language-country format, where language is an ISO 639
* value and country is an ISO 3166 value.
*
* Examples: "en-us", "en-za", "zh-tw", "jp"
*/
userDefaultLanguage: string;
/**
* The time zone of the device when data was uploaded, as seconds skew from UTC.
* Use this to calculate the device's local time for
* [`EventContext.timestamp`](cloud_functions_eventcontext.html#timestamp).
*/
deviceTimeZoneOffsetSeconds: number;
/**
* The device's Limit Ad Tracking setting.
* When `true`, you cannot use `resettableDeviceId` for remarketing, demographics or influencing ads serving
* behaviour. However, you can use `resettableDeviceId` for conversion tracking and campaign attribution.
*/
limitedAdTracking: boolean;
}
/** Interface representing the geographic origin of the events. */
export interface GeoInfo {
/**
* The geographic continent.
*
* Example: "South America".
*/
continent?: string;
/**
* The geographic country.
*
* Example: "Brazil".
*/
country?: string;
/**
* The geographic region.
*
* Example: "State of Sao Paulo".
*/
region?: string;
/**
* The geographic city.
*
* Example: "Sao Paulo".
*/
city?: string;
}
/** Interface representing the application that triggered these events. */
export interface AppInfo {
/**
* The app's version name.
*
* Examples: "1.0", "4.3.1.1.213361", "2.3 (1824253)", "v1.8b22p6".
*/
appVersion?: string;
/**
* Unique ID for this instance of the app.
*
* Example: "71683BF9FA3B4B0D9535A1F05188BAF3".
*/
appInstanceId: string;
/**
* The identifier of the store that installed the app.
*
* Examples: "com.sec.android.app.samsungapps", "com.amazon.venezia", "com.nokia.nstore".
*/
appStore?: string;
/**
* The app platform.
*
* Examples: "ANDROID", "IOS".
*/
appPlatform: string;
/** Unique application identifier within an app store. */
appId?: string;
}
/** Interface representing the bundle these events were uploaded to. */
export declare class ExportBundleInfo {
/** Monotonically increasing index for each bundle set by the Analytics SDK. */
bundleSequenceId: number;
/** Timestamp offset (in milliseconds) between collection time and upload time. */
serverTimestampOffset: number;
/** @hidden */
constructor(wireFormat: any);
}

View File

@@ -0,0 +1,247 @@
"use strict";
// The MIT License (MIT)
//
// Copyright (c) 2017 Firebase
//
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExportBundleInfo = exports.UserPropertyValue = exports.UserDimensions = exports.AnalyticsEvent = exports.AnalyticsEventBuilder = exports._eventWithOptions = exports.event = exports.service = exports.provider = void 0;
const cloud_functions_1 = require("../cloud-functions");
/** @internal */
exports.provider = "google.analytics";
/** @internal */
exports.service = "app-measurement.com";
/**
* Registers a function to handle analytics events.
*
* @param analyticsEventType Name of the analytics event type to which
* this Cloud Function is scoped.
*
* @returns Analytics event builder interface.
*/
function event(analyticsEventType) {
return _eventWithOptions(analyticsEventType, {});
}
exports.event = event;
/** @internal */
function _eventWithOptions(analyticsEventType, options) {
return new AnalyticsEventBuilder(() => {
if (!process.env.GCLOUD_PROJECT) {
throw new Error("process.env.GCLOUD_PROJECT is not set.");
}
return "projects/" + process.env.GCLOUD_PROJECT + "/events/" + analyticsEventType;
}, options);
}
exports._eventWithOptions = _eventWithOptions;
/**
* The Firebase Analytics event builder interface.
*
* Access via `functions.analytics.event()`.
*/
class AnalyticsEventBuilder {
/** @hidden */
constructor(triggerResource, options) {
this.triggerResource = triggerResource;
this.options = options;
}
/**
* Event handler that fires every time a Firebase Analytics event occurs.
*
* @param handler Event handler that fires every time a Firebase Analytics event
* occurs.
*
* @returns A function that you can export and deploy.
*/
onLog(handler) {
const dataConstructor = (raw) => {
return new AnalyticsEvent(raw.data);
};
return (0, cloud_functions_1.makeCloudFunction)({
handler,
provider: exports.provider,
eventType: "event.log",
service: exports.service,
legacyEventType: `providers/google.firebase.analytics/eventTypes/event.log`,
triggerResource: this.triggerResource,
dataConstructor,
options: this.options,
});
}
}
exports.AnalyticsEventBuilder = AnalyticsEventBuilder;
/** Interface representing a Firebase Analytics event that was logged for a specific user. */
class AnalyticsEvent {
/** @hidden */
constructor(wireFormat) {
this.params = {}; // In case of absent field, show empty (not absent) map.
if (wireFormat.eventDim && wireFormat.eventDim.length > 0) {
// If there's an eventDim, there'll always be exactly one.
const eventDim = wireFormat.eventDim[0];
copyField(eventDim, this, "name");
copyField(eventDim, this, "params", (p) => mapKeys(p, unwrapValue));
copyFieldTo(eventDim, this, "valueInUsd", "valueInUSD");
copyFieldTo(eventDim, this, "date", "reportingDate");
copyTimestampToString(eventDim, this, "timestampMicros", "logTime");
copyTimestampToString(eventDim, this, "previousTimestampMicros", "previousLogTime");
}
copyFieldTo(wireFormat, this, "userDim", "user", (dim) => new UserDimensions(dim));
}
}
exports.AnalyticsEvent = AnalyticsEvent;
/**
* Interface representing the user who triggered the events.
*/
class UserDimensions {
/** @hidden */
constructor(wireFormat) {
// These are interfaces or primitives, no transformation needed.
copyFields(wireFormat, this, ["userId", "deviceInfo", "geoInfo", "appInfo"]);
// The following fields do need transformations of some sort.
copyTimestampToString(wireFormat, this, "firstOpenTimestampMicros", "firstOpenTime");
this.userProperties = {}; // With no entries in the wire format, present an empty (as opposed to absent) map.
copyField(wireFormat, this, "userProperties", (r) => {
const entries = Object.entries(r).map(([k, v]) => [k, new UserPropertyValue(v)]);
return Object.fromEntries(entries);
});
copyField(wireFormat, this, "bundleInfo", (r) => new ExportBundleInfo(r));
// BUG(36000368) Remove when no longer necessary
/* tslint:disable:no-string-literal */
if (!this.userId && this.userProperties["user_id"]) {
this.userId = this.userProperties["user_id"].value;
}
/* tslint:enable:no-string-literal */
}
}
exports.UserDimensions = UserDimensions;
/** Predefined or custom properties stored on the client side. */
class UserPropertyValue {
/** @hidden */
constructor(wireFormat) {
copyField(wireFormat, this, "value", unwrapValueAsString);
copyTimestampToString(wireFormat, this, "setTimestampUsec", "setTime");
}
}
exports.UserPropertyValue = UserPropertyValue;
/** Interface representing the bundle these events were uploaded to. */
class ExportBundleInfo {
/** @hidden */
constructor(wireFormat) {
copyField(wireFormat, this, "bundleSequenceId");
copyTimestampToMillis(wireFormat, this, "serverTimestampOffsetMicros", "serverTimestampOffset");
}
}
exports.ExportBundleInfo = ExportBundleInfo;
/** @hidden */
function copyFieldTo(from, to, fromField, toField, transform) {
if (typeof from[fromField] === "undefined") {
return;
}
if (transform) {
to[toField] = transform(from[fromField]);
return;
}
to[toField] = from[fromField];
}
/** @hidden */
function copyField(from, to, field, transform = (from) => from) {
copyFieldTo(from, to, field, field, transform);
}
/** @hidden */
function copyFields(from, to, fields) {
for (const field of fields) {
copyField(from, to, field);
}
}
function mapKeys(obj, transform) {
const entries = Object.entries(obj).map(([k, v]) => [k, transform(v)]);
return Object.fromEntries(entries);
}
// The incoming payload will have fields like:
// {
// 'myInt': {
// 'intValue': '123'
// },
// 'myDouble': {
// 'doubleValue': 1.0
// },
// 'myFloat': {
// 'floatValue': 1.1
// },
// 'myString': {
// 'stringValue': 'hi!'
// }
// }
//
// The following method will remove these four types of 'xValue' fields, flattening them
// to just their values, as a string:
// {
// 'myInt': '123',
// 'myDouble': '1.0',
// 'myFloat': '1.1',
// 'myString': 'hi!'
// }
//
// Note that while 'intValue' will have a quoted payload, 'doubleValue' and 'floatValue' will not. This
// is due to the encoding library, which renders int64 values as strings to avoid loss of precision. This
// method always returns a string, similarly to avoid loss of precision, unlike the less-conservative
// 'unwrapValue' method just below.
/** @hidden */
function unwrapValueAsString(wrapped) {
const key = Object.keys(wrapped)[0];
return wrapped[key].toString();
}
// Ditto as the method above, but returning the values in the idiomatic JavaScript type (string for strings,
// number for numbers):
// {
// 'myInt': 123,
// 'myDouble': 1.0,
// 'myFloat': 1.1,
// 'myString': 'hi!'
// }
//
// The field names in the incoming xValue fields identify the type a value has, which for JavaScript's
// purposes can be divided into 'number' versus 'string'. This method will render all the numbers as
// JavaScript's 'number' type, since we prefer using idiomatic types. Note that this may lead to loss
// in precision for int64 fields, so use with care.
/** @hidden */
const xValueNumberFields = ["intValue", "floatValue", "doubleValue"];
/** @hidden */
function unwrapValue(wrapped) {
const key = Object.keys(wrapped)[0];
const value = unwrapValueAsString(wrapped);
return xValueNumberFields.includes(key) ? Number(value) : value;
}
// The JSON payload delivers timestamp fields as strings of timestamps denoted in microseconds.
// The JavaScript convention is to use numbers denoted in milliseconds. This method
// makes it easy to convert a field of one type into the other.
/** @hidden */
function copyTimestampToMillis(from, to, fromName, toName) {
if (from[fromName] !== undefined) {
to[toName] = Math.round(from[fromName] / 1000);
}
}
// The JSON payload delivers timestamp fields as strings of timestamps denoted in microseconds.
// In our SDK, we'd like to present timestamp as ISO-format strings. This method makes it easy
// to convert a field of one type into the other.
/** @hidden */
function copyTimestampToString(from, to, fromName, toName) {
if (from[fromName] !== undefined) {
to[toName] = new Date(from[fromName] / 1000).toISOString();
}
}

View File

@@ -0,0 +1,73 @@
import { AuthEventContext, AuthUserRecord, BeforeCreateResponse, BeforeEmailResponse, BeforeSignInResponse, BeforeSmsResponse, HttpsError, MaybeAsync, UserInfo, UserRecord, userRecordConstructor, UserRecordMetadata } from "../../common/providers/identity";
import { BlockingFunction, CloudFunction, EventContext } from "../cloud-functions";
export { UserRecord, UserInfo, UserRecordMetadata, userRecordConstructor };
export { HttpsError };
/**
* Options for Auth blocking function.
*/
export interface UserOptions {
/** Options to set configuration at the resource level for blocking functions. */
blockingOptions?: {
/** Pass the ID Token credential to the function. */
idToken?: boolean;
/** Pass the Access Token credential to the function. */
accessToken?: boolean;
/** Pass the Refresh Token credential to the function. */
refreshToken?: boolean;
};
}
/**
* Handles events related to Firebase Auth users events.
*
* @param userOptions - Resource level options
* @returns UserBuilder - Builder used to create functions for Firebase Auth user lifecycle events
*
* @public
*/
export declare function user(userOptions?: UserOptions): UserBuilder;
/**
* Builder used to create functions for Firebase Auth user lifecycle events.
* @public
*/
export declare class UserBuilder {
private triggerResource;
private options;
private userOptions?;
private static dataConstructor;
/**
* Responds to the creation of a Firebase Auth user.
*
* @param handler Event handler that responds to the creation of a Firebase Auth user.
*
* @public
*/
onCreate(handler: (user: UserRecord, context: EventContext) => PromiseLike<any> | any): CloudFunction<UserRecord>;
/**
* Responds to the deletion of a Firebase Auth user.
*
* @param handler Event handler that responds to the deletion of a Firebase Auth user.
*
* @public
*/
onDelete(handler: (user: UserRecord, context: EventContext) => PromiseLike<any> | any): CloudFunction<UserRecord>;
/**
* Blocks request to create a Firebase Auth user.
*
* @param handler Event handler that blocks creation of a Firebase Auth user.
*
* @public
*/
beforeCreate(handler: (user: AuthUserRecord, context: AuthEventContext) => MaybeAsync<BeforeCreateResponse | void>): BlockingFunction;
/**
* Blocks request to sign-in a Firebase Auth user.
*
* @param handler Event handler that blocks sign-in of a Firebase Auth user.
*
* @public
*/
beforeSignIn(handler: (user: AuthUserRecord, context: AuthEventContext) => MaybeAsync<BeforeSignInResponse | void>): BlockingFunction;
beforeEmail(handler: (context: AuthEventContext) => MaybeAsync<BeforeEmailResponse | void>): BlockingFunction;
beforeSms(handler: (context: AuthEventContext) => MaybeAsync<BeforeSmsResponse | void>): BlockingFunction;
private onOperation;
private beforeOperation;
}

View File

@@ -0,0 +1,174 @@
"use strict";
// The MIT License (MIT)
//
// Copyright (c) 2017 Firebase
//
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserBuilder = exports._userWithOptions = exports.user = exports.service = exports.provider = exports.HttpsError = exports.userRecordConstructor = exports.UserRecordMetadata = void 0;
const identity_1 = require("../../common/providers/identity");
Object.defineProperty(exports, "HttpsError", { enumerable: true, get: function () { return identity_1.HttpsError; } });
Object.defineProperty(exports, "userRecordConstructor", { enumerable: true, get: function () { return identity_1.userRecordConstructor; } });
Object.defineProperty(exports, "UserRecordMetadata", { enumerable: true, get: function () { return identity_1.UserRecordMetadata; } });
const cloud_functions_1 = require("../cloud-functions");
const manifest_1 = require("../../runtime/manifest");
/** @internal */
exports.provider = "google.firebase.auth";
/** @internal */
exports.service = "firebaseauth.googleapis.com";
/**
* Handles events related to Firebase Auth users events.
*
* @param userOptions - Resource level options
* @returns UserBuilder - Builder used to create functions for Firebase Auth user lifecycle events
*
* @public
*/
function user(userOptions) {
return _userWithOptions({}, userOptions || {});
}
exports.user = user;
/** @internal */
function _userWithOptions(options, userOptions) {
return new UserBuilder(() => {
if (!process.env.GCLOUD_PROJECT) {
throw new Error("process.env.GCLOUD_PROJECT is not set.");
}
return "projects/" + process.env.GCLOUD_PROJECT;
}, options, userOptions);
}
exports._userWithOptions = _userWithOptions;
/**
* Builder used to create functions for Firebase Auth user lifecycle events.
* @public
*/
class UserBuilder {
static dataConstructor(raw) {
return (0, identity_1.userRecordConstructor)(raw.data);
}
/* @internal */
constructor(triggerResource, options, userOptions) {
this.triggerResource = triggerResource;
this.options = options;
this.userOptions = userOptions;
}
/**
* Responds to the creation of a Firebase Auth user.
*
* @param handler Event handler that responds to the creation of a Firebase Auth user.
*
* @public
*/
onCreate(handler) {
return this.onOperation(handler, "user.create");
}
/**
* Responds to the deletion of a Firebase Auth user.
*
* @param handler Event handler that responds to the deletion of a Firebase Auth user.
*
* @public
*/
onDelete(handler) {
return this.onOperation(handler, "user.delete");
}
/**
* Blocks request to create a Firebase Auth user.
*
* @param handler Event handler that blocks creation of a Firebase Auth user.
*
* @public
*/
beforeCreate(handler) {
return this.beforeOperation(handler, "beforeCreate");
}
/**
* Blocks request to sign-in a Firebase Auth user.
*
* @param handler Event handler that blocks sign-in of a Firebase Auth user.
*
* @public
*/
beforeSignIn(handler) {
return this.beforeOperation(handler, "beforeSignIn");
}
beforeEmail(handler) {
return this.beforeOperation(handler, "beforeSendEmail");
}
beforeSms(handler) {
return this.beforeOperation(handler, "beforeSendSms");
}
onOperation(handler, eventType) {
return (0, cloud_functions_1.makeCloudFunction)({
handler,
provider: exports.provider,
eventType,
service: exports.service,
triggerResource: this.triggerResource,
// eslint-disable-next-line @typescript-eslint/unbound-method
dataConstructor: UserBuilder.dataConstructor,
legacyEventType: `providers/firebase.auth/eventTypes/${eventType}`,
options: this.options,
});
}
beforeOperation(handler, eventType) {
var _a, _b, _c, _d, _e, _f;
const accessToken = ((_b = (_a = this.userOptions) === null || _a === void 0 ? void 0 : _a.blockingOptions) === null || _b === void 0 ? void 0 : _b.accessToken) || false;
const idToken = ((_d = (_c = this.userOptions) === null || _c === void 0 ? void 0 : _c.blockingOptions) === null || _d === void 0 ? void 0 : _d.idToken) || false;
const refreshToken = ((_f = (_e = this.userOptions) === null || _e === void 0 ? void 0 : _e.blockingOptions) === null || _f === void 0 ? void 0 : _f.refreshToken) || false;
const annotatedHandler = Object.assign(handler, { platform: "gcfv1" });
const func = (0, identity_1.wrapHandler)(eventType, annotatedHandler);
const legacyEventType = `providers/cloud.auth/eventTypes/user.${eventType}`;
func.__trigger = {
labels: {},
...(0, cloud_functions_1.optionsToTrigger)(this.options),
blockingTrigger: {
eventType: legacyEventType,
options: {
accessToken,
idToken,
refreshToken,
},
},
};
func.__endpoint = {
platform: "gcfv1",
labels: {},
...(0, manifest_1.initV1Endpoint)(this.options),
...(0, cloud_functions_1.optionsToEndpoint)(this.options),
blockingTrigger: {
eventType: legacyEventType,
options: {
accessToken,
idToken,
refreshToken,
},
},
};
func.__requiredAPIs = [
{
api: "identitytoolkit.googleapis.com",
reason: "Needed for auth blocking functions",
},
];
func.run = handler;
return func;
}
}
exports.UserBuilder = UserBuilder;

View File

@@ -0,0 +1,117 @@
import { Change } from "../../common/change";
import { ParamsOf } from "../../common/params";
import { DataSnapshot } from "../../common/providers/database";
import { CloudFunction, EventContext } from "../cloud-functions";
import { DeploymentOptions } from "../function-configuration";
export { DataSnapshot };
/**
* Registers a function that triggers on events from a specific
* Firebase Realtime Database instance.
*
* @remarks
* Use this method together with `ref` to specify the instance on which to
* watch for database events. For example: `firebase.database.instance('my-app-db-2').ref('/foo/bar')`
*
* Note that `functions.database.ref` used without `instance` watches the
* *default* instance for events.
*
* @param instance The instance name of the database instance
* to watch for write events.
* @returns Firebase Realtime Database instance builder interface.
*/
export declare function instance(instance: string): InstanceBuilder;
/**
* Registers a function that triggers on Firebase Realtime Database write
* events.
*
* @remarks
* This method behaves very similarly to the method of the same name in the
* client and Admin Firebase SDKs. Any change to the Database that affects the
* data at or below the provided `path` will fire an event in Cloud Functions.
*
* There are three important differences between listening to a Realtime
* Database event in Cloud Functions and using the Realtime Database in the
* client and Admin SDKs:
*
* 1. Cloud Functions allows wildcards in the `path` name. Any `path` component
* in curly brackets (`{}`) is a wildcard that matches all strings. The value
* that matched a certain invocation of a Cloud Function is returned as part
* of the [`EventContext.params`](cloud_functions_eventcontext.html#params object. For
* example, `ref("messages/{messageId}")` matches changes at
* `/messages/message1` or `/messages/message2`, resulting in
* `event.params.messageId` being set to `"message1"` or `"message2"`,
* respectively.
*
* 2. Cloud Functions do not fire an event for data that already existed before
* the Cloud Function was deployed.
*
* 3. Cloud Function events have access to more information, including a
* snapshot of the previous event data and information about the user who
* triggered the Cloud Function.
*
* @param path The path within the Database to watch for write events.
* @returns Firebase Realtime Database builder interface.
*/
export declare function ref<Ref extends string>(path: Ref): RefBuilder<Ref>;
/**
* The Firebase Realtime Database instance builder interface.
*
* Access via [`database.instance()`](providers_database_.html#instance).
*/
export declare class InstanceBuilder {
private instance;
private options;
constructor(instance: string, options: DeploymentOptions);
/**
* @returns Firebase Realtime Database reference builder interface.
*/
ref<Ref extends string>(path: Ref): RefBuilder<Ref>;
}
/**
* The Firebase Realtime Database reference builder interface.
*
* Access via [`functions.database.ref()`](functions.database#.ref).
*/
export declare class RefBuilder<Ref extends string> {
private triggerResource;
private options;
constructor(triggerResource: () => string, options: DeploymentOptions);
/**
* Event handler that fires every time a Firebase Realtime Database write
* of any kind (creation, update, or delete) occurs.
*
* @param handler Event handler that runs every time a Firebase Realtime Database
* write occurs.
* @returns A function that you can export and deploy.
*/
onWrite(handler: (change: Change<DataSnapshot>, context: EventContext<ParamsOf<Ref>>) => PromiseLike<any> | any): CloudFunction<Change<DataSnapshot>>;
/**
* Event handler that fires every time data is updated in
* Firebase Realtime Database.
*
* @param handler Event handler which is run every time a Firebase Realtime Database
* write occurs.
* @returns A function which you can export and deploy.
*/
onUpdate(handler: (change: Change<DataSnapshot>, context: EventContext<ParamsOf<Ref>>) => PromiseLike<any> | any): CloudFunction<Change<DataSnapshot>>;
/**
* Event handler that fires every time new data is created in
* Firebase Realtime Database.
*
* @param handler Event handler that runs every time new data is created in
* Firebase Realtime Database.
* @returns A function that you can export and deploy.
*/
onCreate(handler: (snapshot: DataSnapshot, context: EventContext<ParamsOf<Ref>>) => PromiseLike<any> | any): CloudFunction<DataSnapshot>;
/**
* Event handler that fires every time data is deleted from
* Firebase Realtime Database.
*
* @param handler Event handler that runs every time data is deleted from
* Firebase Realtime Database.
* @returns A function that you can export and deploy.
*/
onDelete(handler: (snapshot: DataSnapshot, context: EventContext<ParamsOf<Ref>>) => PromiseLike<any> | any): CloudFunction<DataSnapshot>;
private onOperation;
private changeConstructor;
}

View File

@@ -0,0 +1,263 @@
"use strict";
// The MIT License (MIT)
//
// Copyright (c) 2017 Firebase
//
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractInstanceAndPath = exports.RefBuilder = exports._refWithOptions = exports.InstanceBuilder = exports._instanceWithOptions = exports.ref = exports.instance = exports.service = exports.provider = exports.DataSnapshot = void 0;
const app_1 = require("../../common/app");
const config_1 = require("../../common/config");
const database_1 = require("../../common/providers/database");
Object.defineProperty(exports, "DataSnapshot", { enumerable: true, get: function () { return database_1.DataSnapshot; } });
const path_1 = require("../../common/utilities/path");
const utils_1 = require("../../common/utilities/utils");
const cloud_functions_1 = require("../cloud-functions");
/** @internal */
exports.provider = "google.firebase.database";
/** @internal */
exports.service = "firebaseio.com";
const databaseURLRegex = new RegExp("^https://([^.]+).");
const emulatorDatabaseURLRegex = new RegExp("^http://.*ns=([^&]+)");
/**
* Registers a function that triggers on events from a specific
* Firebase Realtime Database instance.
*
* @remarks
* Use this method together with `ref` to specify the instance on which to
* watch for database events. For example: `firebase.database.instance('my-app-db-2').ref('/foo/bar')`
*
* Note that `functions.database.ref` used without `instance` watches the
* *default* instance for events.
*
* @param instance The instance name of the database instance
* to watch for write events.
* @returns Firebase Realtime Database instance builder interface.
*/
function instance(instance) {
return _instanceWithOptions(instance, {});
}
exports.instance = instance;
/**
* Registers a function that triggers on Firebase Realtime Database write
* events.
*
* @remarks
* This method behaves very similarly to the method of the same name in the
* client and Admin Firebase SDKs. Any change to the Database that affects the
* data at or below the provided `path` will fire an event in Cloud Functions.
*
* There are three important differences between listening to a Realtime
* Database event in Cloud Functions and using the Realtime Database in the
* client and Admin SDKs:
*
* 1. Cloud Functions allows wildcards in the `path` name. Any `path` component
* in curly brackets (`{}`) is a wildcard that matches all strings. The value
* that matched a certain invocation of a Cloud Function is returned as part
* of the [`EventContext.params`](cloud_functions_eventcontext.html#params object. For
* example, `ref("messages/{messageId}")` matches changes at
* `/messages/message1` or `/messages/message2`, resulting in
* `event.params.messageId` being set to `"message1"` or `"message2"`,
* respectively.
*
* 2. Cloud Functions do not fire an event for data that already existed before
* the Cloud Function was deployed.
*
* 3. Cloud Function events have access to more information, including a
* snapshot of the previous event data and information about the user who
* triggered the Cloud Function.
*
* @param path The path within the Database to watch for write events.
* @returns Firebase Realtime Database builder interface.
*/
function ref(path) {
return _refWithOptions(path, {});
}
exports.ref = ref;
/** @internal */
function _instanceWithOptions(instance, options) {
return new InstanceBuilder(instance, options);
}
exports._instanceWithOptions = _instanceWithOptions;
/**
* The Firebase Realtime Database instance builder interface.
*
* Access via [`database.instance()`](providers_database_.html#instance).
*/
class InstanceBuilder {
constructor(instance, options) {
this.instance = instance;
this.options = options;
}
/**
* @returns Firebase Realtime Database reference builder interface.
*/
ref(path) {
const normalized = (0, path_1.normalizePath)(path);
return new RefBuilder(() => `projects/_/instances/${this.instance}/refs/${normalized}`, this.options);
}
}
exports.InstanceBuilder = InstanceBuilder;
/** @internal */
function _refWithOptions(path, options) {
const resourceGetter = () => {
const normalized = (0, path_1.normalizePath)(path);
const databaseURL = (0, config_1.firebaseConfig)().databaseURL;
if (!databaseURL) {
throw new Error("Missing expected firebase config value databaseURL, " +
"config is actually" +
JSON.stringify((0, config_1.firebaseConfig)()) +
"\n If you are unit testing, please set process.env.FIREBASE_CONFIG");
}
let instance;
const prodMatch = databaseURL.match(databaseURLRegex);
if (prodMatch) {
instance = prodMatch[1];
}
else {
const emulatorMatch = databaseURL.match(emulatorDatabaseURLRegex);
if (emulatorMatch) {
instance = emulatorMatch[1];
}
}
if (!instance) {
throw new Error("Invalid value for config firebase.databaseURL: " + databaseURL);
}
return `projects/_/instances/${instance}/refs/${normalized}`;
};
return new RefBuilder(resourceGetter, options);
}
exports._refWithOptions = _refWithOptions;
/**
* The Firebase Realtime Database reference builder interface.
*
* Access via [`functions.database.ref()`](functions.database#.ref).
*/
class RefBuilder {
constructor(triggerResource, options) {
this.triggerResource = triggerResource;
this.options = options;
this.changeConstructor = (raw) => {
const [dbInstance, path] = extractInstanceAndPath(raw.context.resource.name, raw.context.domain);
const before = new database_1.DataSnapshot(raw.data.data, path, (0, app_1.getApp)(), dbInstance);
const after = new database_1.DataSnapshot((0, utils_1.applyChange)(raw.data.data, raw.data.delta), path, (0, app_1.getApp)(), dbInstance);
return {
before,
after,
};
};
}
/**
* Event handler that fires every time a Firebase Realtime Database write
* of any kind (creation, update, or delete) occurs.
*
* @param handler Event handler that runs every time a Firebase Realtime Database
* write occurs.
* @returns A function that you can export and deploy.
*/
onWrite(handler) {
return this.onOperation(handler, "ref.write", this.changeConstructor);
}
/**
* Event handler that fires every time data is updated in
* Firebase Realtime Database.
*
* @param handler Event handler which is run every time a Firebase Realtime Database
* write occurs.
* @returns A function which you can export and deploy.
*/
onUpdate(handler) {
return this.onOperation(handler, "ref.update", this.changeConstructor);
}
/**
* Event handler that fires every time new data is created in
* Firebase Realtime Database.
*
* @param handler Event handler that runs every time new data is created in
* Firebase Realtime Database.
* @returns A function that you can export and deploy.
*/
onCreate(handler) {
const dataConstructor = (raw) => {
const [dbInstance, path] = extractInstanceAndPath(raw.context.resource.name, raw.context.domain);
return new database_1.DataSnapshot(raw.data.delta, path, (0, app_1.getApp)(), dbInstance);
};
return this.onOperation(handler, "ref.create", dataConstructor);
}
/**
* Event handler that fires every time data is deleted from
* Firebase Realtime Database.
*
* @param handler Event handler that runs every time data is deleted from
* Firebase Realtime Database.
* @returns A function that you can export and deploy.
*/
onDelete(handler) {
const dataConstructor = (raw) => {
const [dbInstance, path] = extractInstanceAndPath(raw.context.resource.name, raw.context.domain);
return new database_1.DataSnapshot(raw.data.data, path, (0, app_1.getApp)(), dbInstance);
};
return this.onOperation(handler, "ref.delete", dataConstructor);
}
onOperation(handler, eventType, dataConstructor) {
return (0, cloud_functions_1.makeCloudFunction)({
handler,
provider: exports.provider,
service: exports.service,
eventType,
legacyEventType: `providers/${exports.provider}/eventTypes/${eventType}`,
triggerResource: this.triggerResource,
dataConstructor,
options: this.options,
});
}
}
exports.RefBuilder = RefBuilder;
const resourceRegex = /^projects\/([^/]+)\/instances\/([a-zA-Z0-9-]+)\/refs(\/.+)?/;
/**
* Utility function to extract database reference from resource string
*
* @param optional database domain override for the original of the source database.
* It defaults to `firebaseio.com`.
* Multi-region RTDB will be served from different domains.
* Since region is not part of the resource name, it is provided through context.
*
* @internal
*/
function extractInstanceAndPath(resource, domain = "firebaseio.com") {
const match = resource.match(new RegExp(resourceRegex));
if (!match) {
throw new Error(`Unexpected resource string for Firebase Realtime Database event: ${resource}. ` +
'Expected string in the format of "projects/_/instances/{firebaseioSubdomain}/refs/{ref=**}"');
}
const [, project, dbInstanceName, path] = match;
if (project !== "_") {
throw new Error(`Expect project to be '_' in a Firebase Realtime Database event`);
}
const emuHost = process.env.FIREBASE_DATABASE_EMULATOR_HOST;
if (emuHost) {
const dbInstance = `http://${emuHost}/?ns=${dbInstanceName}`;
return [dbInstance, path];
}
else {
const dbInstance = "https://" + dbInstanceName + "." + domain;
return [dbInstance, path];
}
}
exports.extractInstanceAndPath = extractInstanceAndPath;

View File

@@ -0,0 +1,47 @@
import * as firestore from "firebase-admin/firestore";
import { Change } from "../../common/change";
import { ParamsOf } from "../../common/params";
import { CloudFunction, Event, EventContext } from "../cloud-functions";
import { DeploymentOptions } from "../function-configuration";
export type DocumentSnapshot = firestore.DocumentSnapshot;
export type QueryDocumentSnapshot = firestore.QueryDocumentSnapshot;
/**
* Select the Firestore document to listen to for events.
* @param path Full database path to listen to. This includes the name of
* the collection that the document is a part of. For example, if the
* collection is named "users" and the document is named "Ada", then the
* path is "/users/Ada".
*/
export declare function document<Path extends string>(path: Path): DocumentBuilder<Path>;
export declare function namespace(namespace: string): NamespaceBuilder;
export declare function database(database: string): DatabaseBuilder;
export declare class DatabaseBuilder {
private database;
private options;
constructor(database: string, options: DeploymentOptions);
namespace(namespace: string): NamespaceBuilder;
document<Path extends string>(path: Path): DocumentBuilder<Path>;
}
export declare class NamespaceBuilder {
private database;
private options;
private namespace?;
constructor(database: string, options: DeploymentOptions, namespace?: string);
document<Path extends string>(path: Path): DocumentBuilder<Path>;
}
export declare function snapshotConstructor(event: Event): DocumentSnapshot;
export declare function beforeSnapshotConstructor(event: Event): DocumentSnapshot;
export declare class DocumentBuilder<Path extends string> {
private triggerResource;
private options;
constructor(triggerResource: () => string, options: DeploymentOptions);
/** Respond to all document writes (creates, updates, or deletes). */
onWrite(handler: (change: Change<DocumentSnapshot>, context: EventContext<ParamsOf<Path>>) => PromiseLike<any> | any): CloudFunction<Change<DocumentSnapshot>>;
/** Respond only to document updates. */
onUpdate(handler: (change: Change<QueryDocumentSnapshot>, context: EventContext<ParamsOf<Path>>) => PromiseLike<any> | any): CloudFunction<Change<QueryDocumentSnapshot>>;
/** Respond only to document creations. */
onCreate(handler: (snapshot: QueryDocumentSnapshot, context: EventContext<ParamsOf<Path>>) => PromiseLike<any> | any): CloudFunction<QueryDocumentSnapshot>;
/** Respond only to document deletions. */
onDelete(handler: (snapshot: QueryDocumentSnapshot, context: EventContext<ParamsOf<Path>>) => PromiseLike<any> | any): CloudFunction<QueryDocumentSnapshot>;
private onOperation;
}

View File

@@ -0,0 +1,150 @@
"use strict";
// The MIT License (MIT)
//
// Copyright (c) 2017 Firebase
//
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.DocumentBuilder = exports.beforeSnapshotConstructor = exports.snapshotConstructor = exports.NamespaceBuilder = exports.DatabaseBuilder = exports._documentWithOptions = exports._namespaceWithOptions = exports._databaseWithOptions = exports.database = exports.namespace = exports.document = exports.defaultDatabase = exports.service = exports.provider = void 0;
const path_1 = require("path");
const change_1 = require("../../common/change");
const firestore_1 = require("../../common/providers/firestore");
const cloud_functions_1 = require("../cloud-functions");
/** @internal */
exports.provider = "google.firestore";
/** @internal */
exports.service = "firestore.googleapis.com";
/** @internal */
exports.defaultDatabase = "(default)";
/**
* Select the Firestore document to listen to for events.
* @param path Full database path to listen to. This includes the name of
* the collection that the document is a part of. For example, if the
* collection is named "users" and the document is named "Ada", then the
* path is "/users/Ada".
*/
function document(path) {
return _documentWithOptions(path, {});
}
exports.document = document;
// Multiple namespaces are not yet supported by Firestore.
function namespace(namespace) {
return _namespaceWithOptions(namespace, {});
}
exports.namespace = namespace;
// Multiple databases are not yet supported by Firestore.
function database(database) {
return _databaseWithOptions(database, {});
}
exports.database = database;
/** @internal */
function _databaseWithOptions(database = exports.defaultDatabase, options) {
return new DatabaseBuilder(database, options);
}
exports._databaseWithOptions = _databaseWithOptions;
/** @internal */
function _namespaceWithOptions(namespace, options) {
return _databaseWithOptions(exports.defaultDatabase, options).namespace(namespace);
}
exports._namespaceWithOptions = _namespaceWithOptions;
/** @internal */
function _documentWithOptions(path, options) {
return _databaseWithOptions(exports.defaultDatabase, options).document(path);
}
exports._documentWithOptions = _documentWithOptions;
class DatabaseBuilder {
constructor(database, options) {
this.database = database;
this.options = options;
}
namespace(namespace) {
return new NamespaceBuilder(this.database, this.options, namespace);
}
document(path) {
return new NamespaceBuilder(this.database, this.options).document(path);
}
}
exports.DatabaseBuilder = DatabaseBuilder;
class NamespaceBuilder {
constructor(database, options, namespace) {
this.database = database;
this.options = options;
this.namespace = namespace;
}
document(path) {
return new DocumentBuilder(() => {
if (!process.env.GCLOUD_PROJECT) {
throw new Error("process.env.GCLOUD_PROJECT is not set.");
}
const database = path_1.posix.join("projects", process.env.GCLOUD_PROJECT, "databases", this.database);
return path_1.posix.join(database, this.namespace ? `documents@${this.namespace}` : "documents", path);
}, this.options);
}
}
exports.NamespaceBuilder = NamespaceBuilder;
function snapshotConstructor(event) {
var _a, _b, _c, _d;
return (0, firestore_1.createSnapshotFromJson)(event.data, event.context.resource.name, (_b = (_a = event === null || event === void 0 ? void 0 : event.data) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.readTime, (_d = (_c = event === null || event === void 0 ? void 0 : event.data) === null || _c === void 0 ? void 0 : _c.value) === null || _d === void 0 ? void 0 : _d.updateTime);
}
exports.snapshotConstructor = snapshotConstructor;
// TODO remove this function when wire format changes to new format
function beforeSnapshotConstructor(event) {
var _a, _b;
return (0, firestore_1.createBeforeSnapshotFromJson)(event.data, event.context.resource.name, (_b = (_a = event === null || event === void 0 ? void 0 : event.data) === null || _a === void 0 ? void 0 : _a.oldValue) === null || _b === void 0 ? void 0 : _b.readTime, undefined);
}
exports.beforeSnapshotConstructor = beforeSnapshotConstructor;
function changeConstructor(raw) {
return change_1.Change.fromObjects(beforeSnapshotConstructor(raw), snapshotConstructor(raw));
}
class DocumentBuilder {
constructor(triggerResource, options) {
this.triggerResource = triggerResource;
this.options = options;
// TODO what validation do we want to do here?
}
/** Respond to all document writes (creates, updates, or deletes). */
onWrite(handler) {
return this.onOperation(handler, "document.write", changeConstructor);
}
/** Respond only to document updates. */
onUpdate(handler) {
return this.onOperation(handler, "document.update", changeConstructor);
}
/** Respond only to document creations. */
onCreate(handler) {
return this.onOperation(handler, "document.create", snapshotConstructor);
}
/** Respond only to document deletions. */
onDelete(handler) {
return this.onOperation(handler, "document.delete", beforeSnapshotConstructor);
}
onOperation(handler, eventType, dataConstructor) {
return (0, cloud_functions_1.makeCloudFunction)({
handler,
provider: exports.provider,
eventType,
service: exports.service,
triggerResource: this.triggerResource,
legacyEventType: `providers/cloud.firestore/eventTypes/${eventType}`,
dataConstructor,
options: this.options,
});
}
}
exports.DocumentBuilder = DocumentBuilder;

View File

@@ -0,0 +1,15 @@
import * as express from "express";
import { CallableContext, FunctionsErrorCode, HttpsError, Request } from "../../common/providers/https";
import { HttpsFunction, Runnable } from "../cloud-functions";
export { Request, CallableContext, FunctionsErrorCode, HttpsError };
/**
* Handle HTTP requests.
* @param handler A function that takes a request and response object,
* same signature as an Express app.
*/
export declare function onRequest(handler: (req: Request, resp: express.Response) => void | Promise<void>): HttpsFunction;
/**
* Declares a callable method for clients to call using a Firebase SDK.
* @param handler A method that takes a data and context and returns a value.
*/
export declare function onCall(handler: (data: any, context: CallableContext) => any | Promise<any>): HttpsFunction & Runnable<any>;

View File

@@ -0,0 +1,99 @@
"use strict";
// The MIT License (MIT)
//
// Copyright (c) 2017 Firebase
//
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports._onCallWithOptions = exports._onRequestWithOptions = exports.onCall = exports.onRequest = exports.HttpsError = void 0;
const encoding_1 = require("../../common/encoding");
const https_1 = require("../../common/providers/https");
Object.defineProperty(exports, "HttpsError", { enumerable: true, get: function () { return https_1.HttpsError; } });
const cloud_functions_1 = require("../cloud-functions");
const manifest_1 = require("../../runtime/manifest");
const onInit_1 = require("../../common/onInit");
const trace_1 = require("../../v2/trace");
/**
* Handle HTTP requests.
* @param handler A function that takes a request and response object,
* same signature as an Express app.
*/
function onRequest(handler) {
return _onRequestWithOptions(handler, {});
}
exports.onRequest = onRequest;
/**
* Declares a callable method for clients to call using a Firebase SDK.
* @param handler A method that takes a data and context and returns a value.
*/
function onCall(handler) {
return _onCallWithOptions(handler, {});
}
exports.onCall = onCall;
/** @internal */
function _onRequestWithOptions(handler, options) {
// lets us add __endpoint without altering handler:
const cloudFunction = (req, res) => {
return (0, trace_1.wrapTraceContext)((0, onInit_1.withInit)(handler))(req, res);
};
cloudFunction.__trigger = {
...(0, cloud_functions_1.optionsToTrigger)(options),
httpsTrigger: {},
};
(0, encoding_1.convertIfPresent)(cloudFunction.__trigger.httpsTrigger, options, "invoker", "invoker", encoding_1.convertInvoker);
// TODO parse the options
cloudFunction.__endpoint = {
platform: "gcfv1",
...(0, manifest_1.initV1Endpoint)(options),
...(0, cloud_functions_1.optionsToEndpoint)(options),
httpsTrigger: {},
};
(0, encoding_1.convertIfPresent)(cloudFunction.__endpoint.httpsTrigger, options, "invoker", "invoker", encoding_1.convertInvoker);
return cloudFunction;
}
exports._onRequestWithOptions = _onRequestWithOptions;
/** @internal */
function _onCallWithOptions(handler, options) {
// fix the length of handler to make the call to handler consistent
// in the onCallHandler
const fixedLen = (data, context) => {
return (0, onInit_1.withInit)(handler)(data, context);
};
const func = (0, trace_1.wrapTraceContext)((0, https_1.onCallHandler)({
enforceAppCheck: options.enforceAppCheck,
consumeAppCheckToken: options.consumeAppCheckToken,
cors: { origin: true, methods: "POST" },
}, fixedLen, "gcfv1"));
func.__trigger = {
labels: {},
...(0, cloud_functions_1.optionsToTrigger)(options),
httpsTrigger: {},
};
func.__trigger.labels["deployment-callable"] = "true";
func.__endpoint = {
platform: "gcfv1",
labels: {},
...(0, manifest_1.initV1Endpoint)(options),
...(0, cloud_functions_1.optionsToEndpoint)(options),
callableTrigger: {},
};
func.run = fixedLen;
return func;
}
exports._onCallWithOptions = _onCallWithOptions;

View File

@@ -0,0 +1,93 @@
import { CloudFunction, EventContext } from "../cloud-functions";
import { DeploymentOptions, ScheduleRetryConfig } from "../function-configuration";
/**
* Registers a Cloud Function triggered when a Google Cloud Pub/Sub message
* is sent to a specified topic.
*
* @param topic - The Pub/Sub topic to watch for message events.
* @returns Pub/Sub topic builder interface.
*/
export declare function topic(topic: string): TopicBuilder;
/**
* The Google Cloud Pub/Sub topic builder.
*
* Access via `functions.pubsub.topic()`.
*/
export declare class TopicBuilder {
private triggerResource;
private options;
/** @hidden */
constructor(triggerResource: () => string, options: DeploymentOptions);
/**
* Event handler that fires every time a Cloud Pub/Sub message is
* published.
*
* @param handler - Event handler that runs every time a Cloud Pub/Sub message
* is published.
* @returns A function that you can export and deploy.
*/
onPublish(handler: (message: Message, context: EventContext) => PromiseLike<any> | any): CloudFunction<Message>;
}
/**
* Registers a Cloud Function to run at specified times.
*
* @param schedule - The schedule, in Unix Crontab or AppEngine syntax.
* @returns ScheduleBuilder interface.
*/
export declare function schedule(schedule: string): ScheduleBuilder;
/**
* The builder for scheduled functions, which are powered by
* Google Pub/Sub and Cloud Scheduler. Describes the Cloud Scheduler
* job that is deployed to trigger a scheduled function at the provided
* frequency. For more information, see
* [Schedule functions](/docs/functions/schedule-functions).
*
* Access via `functions.pubsub.schedule()`.
*/
export declare class ScheduleBuilder {
private triggerResource;
private options;
/** @hidden */
constructor(triggerResource: () => string, options: DeploymentOptions);
retryConfig(config: ScheduleRetryConfig): ScheduleBuilder;
timeZone(timeZone: string): ScheduleBuilder;
/**
* Event handler for scheduled functions. Triggered whenever the associated
* scheduler job sends a Pub/Sub message.
*
* @param handler - Handler that fires whenever the associated
* scheduler job sends a Pub/Sub message.
* @returns A function that you can export and deploy.
*/
onRun(handler: (context: EventContext) => PromiseLike<any> | any): CloudFunction<unknown>;
}
/**
* Interface representing a Google Cloud Pub/Sub message.
*
* @param data - Payload of a Pub/Sub message.
*/
export declare class Message {
/**
* The data payload of this message object as a base64-encoded string.
*/
readonly data: string;
/**
* User-defined attributes published with the message, if any.
*/
readonly attributes: {
[key: string]: string;
};
/** @hidden */
private _json;
constructor(data: any);
/**
* The JSON data payload of this message object, if any.
*/
get json(): any;
/**
* Returns a JSON-serializable representation of this object.
*
* @returns A JSON-serializable representation of this object.
*/
toJSON(): any;
}

View File

@@ -0,0 +1,186 @@
"use strict";
// The MIT License (MIT)
//
// Copyright (c) 2017 Firebase
//
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.Message = exports.ScheduleBuilder = exports._scheduleWithOptions = exports.schedule = exports.TopicBuilder = exports._topicWithOptions = exports.topic = exports.service = exports.provider = void 0;
const cloud_functions_1 = require("../cloud-functions");
/** @internal */
exports.provider = "google.pubsub";
/** @internal */
exports.service = "pubsub.googleapis.com";
/**
* Registers a Cloud Function triggered when a Google Cloud Pub/Sub message
* is sent to a specified topic.
*
* @param topic - The Pub/Sub topic to watch for message events.
* @returns Pub/Sub topic builder interface.
*/
function topic(topic) {
return _topicWithOptions(topic, {});
}
exports.topic = topic;
/** @internal */
function _topicWithOptions(topic, options) {
if (topic.indexOf("/") !== -1) {
throw new Error("Topic name may not have a /");
}
return new TopicBuilder(() => {
if (!process.env.GCLOUD_PROJECT) {
throw new Error("process.env.GCLOUD_PROJECT is not set.");
}
return `projects/${process.env.GCLOUD_PROJECT}/topics/${topic}`;
}, options);
}
exports._topicWithOptions = _topicWithOptions;
/**
* The Google Cloud Pub/Sub topic builder.
*
* Access via `functions.pubsub.topic()`.
*/
class TopicBuilder {
/** @hidden */
constructor(triggerResource, options) {
this.triggerResource = triggerResource;
this.options = options;
}
/**
* Event handler that fires every time a Cloud Pub/Sub message is
* published.
*
* @param handler - Event handler that runs every time a Cloud Pub/Sub message
* is published.
* @returns A function that you can export and deploy.
*/
onPublish(handler) {
return (0, cloud_functions_1.makeCloudFunction)({
handler,
provider: exports.provider,
service: exports.service,
triggerResource: this.triggerResource,
eventType: "topic.publish",
dataConstructor: (raw) => new Message(raw.data),
options: this.options,
});
}
}
exports.TopicBuilder = TopicBuilder;
/**
* Registers a Cloud Function to run at specified times.
*
* @param schedule - The schedule, in Unix Crontab or AppEngine syntax.
* @returns ScheduleBuilder interface.
*/
function schedule(schedule) {
return _scheduleWithOptions(schedule, {});
}
exports.schedule = schedule;
/** @internal */
function _scheduleWithOptions(schedule, options) {
const triggerResource = () => {
if (!process.env.GCLOUD_PROJECT) {
throw new Error("process.env.GCLOUD_PROJECT is not set.");
}
// The CLI will append the correct topic name based on region and function name
return `projects/${process.env.GCLOUD_PROJECT}/topics`;
};
return new ScheduleBuilder(triggerResource, {
...options,
schedule: { schedule },
});
}
exports._scheduleWithOptions = _scheduleWithOptions;
/**
* The builder for scheduled functions, which are powered by
* Google Pub/Sub and Cloud Scheduler. Describes the Cloud Scheduler
* job that is deployed to trigger a scheduled function at the provided
* frequency. For more information, see
* [Schedule functions](/docs/functions/schedule-functions).
*
* Access via `functions.pubsub.schedule()`.
*/
class ScheduleBuilder {
/** @hidden */
constructor(triggerResource, options) {
this.triggerResource = triggerResource;
this.options = options;
}
retryConfig(config) {
this.options.schedule.retryConfig = config;
return this;
}
timeZone(timeZone) {
this.options.schedule.timeZone = timeZone;
return this;
}
/**
* Event handler for scheduled functions. Triggered whenever the associated
* scheduler job sends a Pub/Sub message.
*
* @param handler - Handler that fires whenever the associated
* scheduler job sends a Pub/Sub message.
* @returns A function that you can export and deploy.
*/
onRun(handler) {
const cloudFunction = (0, cloud_functions_1.makeCloudFunction)({
contextOnlyHandler: handler,
provider: exports.provider,
service: exports.service,
triggerResource: this.triggerResource,
eventType: "topic.publish",
options: this.options,
labels: { "deployment-scheduled": "true" },
});
return cloudFunction;
}
}
exports.ScheduleBuilder = ScheduleBuilder;
/**
* Interface representing a Google Cloud Pub/Sub message.
*
* @param data - Payload of a Pub/Sub message.
*/
class Message {
constructor(data) {
[this.data, this.attributes, this._json] = [data.data, data.attributes || {}, data.json];
}
/**
* The JSON data payload of this message object, if any.
*/
get json() {
if (typeof this._json === "undefined") {
this._json = JSON.parse(Buffer.from(this.data, "base64").toString("utf8"));
}
return this._json;
}
/**
* Returns a JSON-serializable representation of this object.
*
* @returns A JSON-serializable representation of this object.
*/
toJSON() {
return {
data: this.data,
attributes: this.attributes,
};
}
}
exports.Message = Message;

View File

@@ -0,0 +1,71 @@
import { CloudFunction, EventContext } from "../cloud-functions";
/**
* Registers a function that triggers on Firebase Remote Config template
* update events.
*
* @param handler A function that takes the updated Remote Config
* template version metadata as an argument.
*
* @returns A function that you can export and deploy.
*/
export declare function onUpdate(handler: (version: TemplateVersion, context: EventContext) => PromiseLike<any> | any): CloudFunction<TemplateVersion>;
/** Builder used to create Cloud Functions for Remote Config. */
export declare class UpdateBuilder {
private triggerResource;
private options;
/**
* Handle all updates (including rollbacks) that affect a Remote Config
* project.
* @param handler A function that takes the updated Remote Config template
* version metadata as an argument.
*/
onUpdate(handler: (version: TemplateVersion, context: EventContext) => PromiseLike<any> | any): CloudFunction<TemplateVersion>;
}
/**
* An interface representing a Remote Config template version metadata object
* emitted when a project is updated.
*/
export interface TemplateVersion {
/** The version number of the updated Remote Config template. */
versionNumber: number;
/** When the template was updated in format (ISO8601 timestamp). */
updateTime: string;
/**
* Metadata about the account that performed the update, of
* type [`RemoteConfigUser`](/docs/reference/remote-config/rest/v1/Version#remoteconfiguser).
*/
updateUser: RemoteConfigUser;
/** A description associated with this Remote Config template version. */
description: string;
/**
* The origin of the caller - either the Firebase console or the Remote Config
* REST API. See [`RemoteConfigUpdateOrigin`](/docs/reference/remote-config/rest/v1/Version#remoteconfigupdateorigin)
* for valid values.
*/
updateOrigin: string;
/**
* The type of update action that was performed, whether forced,
* incremental, or a rollback operation. See
* [`RemoteConfigUpdateType`](/docs/reference/remote-config/rest/v1/Version#remoteconfigupdatetype)
* for valid values.
*/
updateType: string;
/**
* The version number of the Remote Config template that this update rolled back to.
* Only applies if this update was a rollback.
*/
rollbackSource?: number;
}
/**
* An interface representing metadata for a Remote Config account
* that performed the update. Contains the same fields as
* [`RemoteConfigUser`](/docs/reference/remote-config/rest/v1/Version#remoteconfiguser).
*/
export interface RemoteConfigUser {
/** Name of the Remote Config account that performed the update. */
name?: string;
/** Email address of the Remote Config account that performed the update. */
email: string;
/** Image URL of the Remote Config account that performed the update. */
imageUrl?: string;
}

View File

@@ -0,0 +1,78 @@
"use strict";
// The MIT License (MIT)
//
// Copyright (c) 2018 Firebase
//
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.UpdateBuilder = exports._onUpdateWithOptions = exports.onUpdate = exports.service = exports.provider = void 0;
const cloud_functions_1 = require("../cloud-functions");
/** @internal */
exports.provider = "google.firebase.remoteconfig";
/** @internal */
exports.service = "firebaseremoteconfig.googleapis.com";
/**
* Registers a function that triggers on Firebase Remote Config template
* update events.
*
* @param handler A function that takes the updated Remote Config
* template version metadata as an argument.
*
* @returns A function that you can export and deploy.
*/
function onUpdate(handler) {
return _onUpdateWithOptions(handler, {});
}
exports.onUpdate = onUpdate;
/** @internal */
function _onUpdateWithOptions(handler, options) {
const triggerResource = () => {
if (!process.env.GCLOUD_PROJECT) {
throw new Error("process.env.GCLOUD_PROJECT is not set.");
}
return `projects/${process.env.GCLOUD_PROJECT}`;
};
return new UpdateBuilder(triggerResource, options).onUpdate(handler);
}
exports._onUpdateWithOptions = _onUpdateWithOptions;
/** Builder used to create Cloud Functions for Remote Config. */
class UpdateBuilder {
/** @internal */
constructor(triggerResource, options) {
this.triggerResource = triggerResource;
this.options = options;
}
/**
* Handle all updates (including rollbacks) that affect a Remote Config
* project.
* @param handler A function that takes the updated Remote Config template
* version metadata as an argument.
*/
onUpdate(handler) {
return (0, cloud_functions_1.makeCloudFunction)({
handler,
provider: exports.provider,
service: exports.service,
triggerResource: this.triggerResource,
eventType: "update",
options: this.options,
});
}
}
exports.UpdateBuilder = UpdateBuilder;

View File

@@ -0,0 +1,220 @@
import { CloudFunction, EventContext } from "../cloud-functions";
/**
* Registers a Cloud Function scoped to a specific storage bucket.
*
* @param bucket Name of the bucket to which this Cloud Function is
* scoped.
*
* @returns Storage bucket builder interface.
*/
export declare function bucket(bucket?: string): BucketBuilder;
/**
* Registers a Cloud Function scoped to the default storage bucket for the
* project.
*
* @returns Storage object builder interface.
*/
export declare function object(): ObjectBuilder;
/**
* The Google Cloud Storage bucket builder interface.
*
* Access via `functions.storage.bucket()`.
*/
export declare class BucketBuilder {
private triggerResource;
private options;
/**
* Event handler which fires every time a Google Cloud Storage change occurs.
*
* @returns Storage object builder interface scoped to the specified storage
* bucket.
*/
object(): ObjectBuilder;
}
/**
* The Google Cloud Storage object builder interface.
*
* Access via `functions.storage.object()`.
*/
export declare class ObjectBuilder {
private triggerResource;
private options;
/**
* Event handler sent only when a bucket has enabled object versioning.
* This event indicates that the live version of an object has become an
* archived version, either because it was archived or because it was
* overwritten by the upload of an object of the same name.
*
* @param handler Event handler which is run every time a Google Cloud Storage
* archival occurs.
*
* @returns A function which you can export and deploy.
*/
onArchive(handler: (object: ObjectMetadata, context: EventContext) => PromiseLike<any> | any): CloudFunction<ObjectMetadata>;
/**
* Event handler which fires every time a Google Cloud Storage deletion occurs.
*
* Sent when an object has been permanently deleted. This includes objects
* that are overwritten or are deleted as part of the bucket's lifecycle
* configuration. For buckets with object versioning enabled, this is not
* sent when an object is archived, even if archival occurs
* via the `storage.objects.delete` method.
*
* @param handler Event handler which is run every time a Google Cloud Storage
* deletion occurs.
*
* @returns A function which you can export and deploy.
*/
onDelete(handler: (object: ObjectMetadata, context: EventContext) => PromiseLike<any> | any): CloudFunction<ObjectMetadata>;
/**
* Event handler which fires every time a Google Cloud Storage object
* creation occurs.
*
* Sent when a new object (or a new generation of an existing object)
* is successfully created in the bucket. This includes copying or rewriting
* an existing object. A failed upload does not trigger this event.
*
* @param handler Event handler which is run every time a Google Cloud Storage
* object creation occurs.
*
* @returns A function which you can export and deploy.
*/
onFinalize(handler: (object: ObjectMetadata, context: EventContext) => PromiseLike<any> | any): CloudFunction<ObjectMetadata>;
/**
* Event handler which fires every time the metadata of an existing object
* changes.
*
* @param handler Event handler which is run every time a Google Cloud Storage
* metadata update occurs.
*
* @returns A function which you can export and deploy.
*/
onMetadataUpdate(handler: (object: ObjectMetadata, context: EventContext) => PromiseLike<any> | any): CloudFunction<ObjectMetadata>;
/** @hidden */
private onOperation;
}
/** Interface representing a Google Google Cloud Storage object metadata object. */
export interface ObjectMetadata {
/** The kind of the object, which is always `storage#object`. */
kind: string;
/**
* The ID of the object, including the bucket name, object name, and
* generation number.
*/
id: string;
/** Storage bucket that contains the object. */
bucket: string;
/** Storage class of the object. */
storageClass: string;
/**
* The value of the `Content-Length` header, used to determine the length of
* the object data in bytes.
*/
size: string;
/** The creation time of the object in RFC 3339 format. */
timeCreated: string;
/**
* The modification time of the object metadata in RFC 3339 format.
*/
updated: string;
/** Link to access the object, assuming you have sufficient permissions. */
selfLink?: string;
/** The object's name. */
name?: string;
/**
* Generation version number that changes each time the object is
* overwritten.
*/
generation?: string;
/** The object's content type, also known as the MIME type. */
contentType?: string;
/**
* Meta-generation version number that changes each time the object's metadata
* is updated.
*/
metageneration?: string;
/**
* The deletion time of the object in RFC 3339 format. Returned
* only if this version of the object has been deleted.
*/
timeDeleted?: string;
timeStorageClassUpdated?: string;
/**
* MD5 hash for the object. All Google Cloud Storage objects
* have a CRC32C hash or MD5 hash.
*/
md5Hash?: string;
/** Media download link. */
mediaLink?: string;
/**
* Content-Encoding to indicate that an object is compressed
* (for example, with gzip compression) while maintaining its Content-Type.
*/
contentEncoding?: string;
/**
* The value of the `Content-Disposition` header, used to specify presentation
* information about the data being transmitted.
*/
contentDisposition?: string;
/** ISO 639-1 language code of the content. */
contentLanguage?: string;
/**
* The value of the `Cache-Control` header, used to determine whether Internet
* caches are allowed to cache public data for an object.
*/
cacheControl?: string;
/** User-provided metadata. */
metadata?: {
[key: string]: string;
};
acl?: [
{
kind?: string;
id?: string;
selfLink?: string;
bucket?: string;
object?: string;
generation?: string;
entity?: string;
role?: string;
email?: string;
entityId?: string;
domain?: string;
projectTeam?: {
projectNumber?: string;
team?: string;
};
etag?: string;
}
];
owner?: {
entity?: string;
entityId?: string;
};
/**
* The object's CRC32C hash. All Google Cloud Storage objects
* have a CRC32C hash or MD5 hash.
*/
crc32c?: string;
/**
* Specifies the number of originally uploaded objects from which
* a composite object was created.
*/
componentCount?: string;
etag?: string;
/**
* Customer-supplied encryption key.
*
* This object contains the following properties:
* * `encryptionAlgorithm` (`string|undefined`): The encryption algorithm that
* was used. Always contains the value `AES256`.
* * `keySha256` (`string|undefined`): An RFC 4648 base64-encoded string of the
* SHA256 hash of your encryption key. You can use this SHA256 hash to
* uniquely identify the AES-256 encryption key required to decrypt the
* object, which you must store securely.
*/
customerEncryption?: {
encryptionAlgorithm?: string;
keySha256?: string;
};
}

View File

@@ -0,0 +1,178 @@
"use strict";
// The MIT License (MIT)
//
// Copyright (c) 2017 Firebase
//
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ObjectBuilder = exports.BucketBuilder = exports._objectWithOptions = exports._bucketWithOptions = exports.object = exports.bucket = exports.service = exports.provider = void 0;
const config_1 = require("../../common/config");
const cloud_functions_1 = require("../cloud-functions");
/** @internal */
exports.provider = "google.storage";
/** @internal */
exports.service = "storage.googleapis.com";
/**
* Registers a Cloud Function scoped to a specific storage bucket.
*
* @param bucket Name of the bucket to which this Cloud Function is
* scoped.
*
* @returns Storage bucket builder interface.
*/
function bucket(bucket) {
return _bucketWithOptions({}, bucket);
}
exports.bucket = bucket;
/**
* Registers a Cloud Function scoped to the default storage bucket for the
* project.
*
* @returns Storage object builder interface.
*/
function object() {
return _objectWithOptions({});
}
exports.object = object;
/** @internal */
function _bucketWithOptions(options, bucket) {
const resourceGetter = () => {
bucket = bucket || (0, config_1.firebaseConfig)().storageBucket;
if (!bucket) {
throw new Error("Missing bucket name. If you are unit testing, please provide a bucket name" +
" through `functions.storage.bucket(bucketName)`, or set process.env.FIREBASE_CONFIG.");
}
if (!/^[a-z\d][a-z\d\\._-]{1,230}[a-z\d]$/.test(bucket)) {
throw new Error(`Invalid bucket name ${bucket}`);
}
return `projects/_/buckets/${bucket}`;
};
return new BucketBuilder(resourceGetter, options);
}
exports._bucketWithOptions = _bucketWithOptions;
/** @internal */
function _objectWithOptions(options) {
return _bucketWithOptions(options).object();
}
exports._objectWithOptions = _objectWithOptions;
/**
* The Google Cloud Storage bucket builder interface.
*
* Access via `functions.storage.bucket()`.
*/
class BucketBuilder {
/** @internal */
constructor(triggerResource, options) {
this.triggerResource = triggerResource;
this.options = options;
}
/**
* Event handler which fires every time a Google Cloud Storage change occurs.
*
* @returns Storage object builder interface scoped to the specified storage
* bucket.
*/
object() {
return new ObjectBuilder(this.triggerResource, this.options);
}
}
exports.BucketBuilder = BucketBuilder;
/**
* The Google Cloud Storage object builder interface.
*
* Access via `functions.storage.object()`.
*/
class ObjectBuilder {
/** @internal */
constructor(triggerResource, options) {
this.triggerResource = triggerResource;
this.options = options;
}
/**
* Event handler sent only when a bucket has enabled object versioning.
* This event indicates that the live version of an object has become an
* archived version, either because it was archived or because it was
* overwritten by the upload of an object of the same name.
*
* @param handler Event handler which is run every time a Google Cloud Storage
* archival occurs.
*
* @returns A function which you can export and deploy.
*/
onArchive(handler) {
return this.onOperation(handler, "object.archive");
}
/**
* Event handler which fires every time a Google Cloud Storage deletion occurs.
*
* Sent when an object has been permanently deleted. This includes objects
* that are overwritten or are deleted as part of the bucket's lifecycle
* configuration. For buckets with object versioning enabled, this is not
* sent when an object is archived, even if archival occurs
* via the `storage.objects.delete` method.
*
* @param handler Event handler which is run every time a Google Cloud Storage
* deletion occurs.
*
* @returns A function which you can export and deploy.
*/
onDelete(handler) {
return this.onOperation(handler, "object.delete");
}
/**
* Event handler which fires every time a Google Cloud Storage object
* creation occurs.
*
* Sent when a new object (or a new generation of an existing object)
* is successfully created in the bucket. This includes copying or rewriting
* an existing object. A failed upload does not trigger this event.
*
* @param handler Event handler which is run every time a Google Cloud Storage
* object creation occurs.
*
* @returns A function which you can export and deploy.
*/
onFinalize(handler) {
return this.onOperation(handler, "object.finalize");
}
/**
* Event handler which fires every time the metadata of an existing object
* changes.
*
* @param handler Event handler which is run every time a Google Cloud Storage
* metadata update occurs.
*
* @returns A function which you can export and deploy.
*/
onMetadataUpdate(handler) {
return this.onOperation(handler, "object.metadataUpdate");
}
/** @hidden */
onOperation(handler, eventType) {
return (0, cloud_functions_1.makeCloudFunction)({
handler,
provider: exports.provider,
service: exports.service,
eventType,
triggerResource: this.triggerResource,
options: this.options,
});
}
}
exports.ObjectBuilder = ObjectBuilder;

View File

@@ -0,0 +1,61 @@
import * as express from "express";
import { Request } from "../../common/providers/https";
import { RateLimits, RetryConfig, TaskContext } from "../../common/providers/tasks";
import { ManifestEndpoint, ManifestRequiredAPI } from "../../runtime/manifest";
export { RetryConfig, RateLimits, TaskContext };
/**
* Options for configuring the task queue to listen to.
*/
export interface TaskQueueOptions {
/** How a task should be retried in the event of a non-2xx return. */
retryConfig?: RetryConfig;
/** How congestion control should be applied to the function. */
rateLimits?: RateLimits;
/**
* Who can enqueue tasks for this function.
* If left unspecified, only service accounts which have
* `roles/cloudtasks.enqueuer` and `roles/cloudfunctions.invoker`
* will have permissions.
*/
invoker?: "private" | string | string[];
}
/**
* A handler for tasks.
*/
export interface TaskQueueFunction {
(req: Request, res: express.Response): Promise<void>;
/** @alpha */
__trigger: unknown;
/** @alpha */
__endpoint: ManifestEndpoint;
/** @alpha */
__requiredAPIs?: ManifestRequiredAPI[];
/**
* The callback passed to the `TaskQueueFunction` constructor.
* @param data - The body enqueued into a task queue.
* @param context - The request context of the enqueued task
* @returns Any return value. Google Cloud Functions will await any promise
* before shutting down your function. Resolved return values
* are only used for unit testing purposes.
*/
run(data: any, context: TaskContext): void | Promise<void>;
}
/**
* Builder for creating a `TaskQueueFunction`.
*/
export declare class TaskQueueBuilder {
private readonly tqOpts?;
private readonly depOpts?;
/**
* Creates a handler for tasks sent to a Google Cloud Tasks queue.
* @param handler - A callback to handle task requests.
* @returns A function you can export and deploy.
*/
onDispatch(handler: (data: any, context: TaskContext) => void | Promise<void>): TaskQueueFunction;
}
/**
* Declares a function that can handle tasks enqueued using the Firebase Admin SDK.
* @param options - Configuration for the Task Queue that feeds into this function.
* Omitting options will configure a Task Queue with default settings.
*/
export declare function taskQueue(options?: TaskQueueOptions): TaskQueueBuilder;

View File

@@ -0,0 +1,85 @@
"use strict";
// The MIT License (MIT)
//
// Copyright (c) 2022 Firebase
//
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.taskQueue = exports.TaskQueueBuilder = void 0;
const encoding_1 = require("../../common/encoding");
const tasks_1 = require("../../common/providers/tasks");
const manifest_1 = require("../../runtime/manifest");
const cloud_functions_1 = require("../cloud-functions");
/**
* Builder for creating a `TaskQueueFunction`.
*/
class TaskQueueBuilder {
/** @internal */
constructor(tqOpts, depOpts) {
this.tqOpts = tqOpts;
this.depOpts = depOpts;
}
/**
* Creates a handler for tasks sent to a Google Cloud Tasks queue.
* @param handler - A callback to handle task requests.
* @returns A function you can export and deploy.
*/
onDispatch(handler) {
var _a, _b;
// onEnqueueHandler sniffs the function length of the passed-in callback
// and the user could have only tried to listen to data. Wrap their handler
// in another handler to avoid accidentally triggering the v2 API
const fixedLen = (data, context) => handler(data, context);
const func = (0, tasks_1.onDispatchHandler)(fixedLen);
func.__trigger = {
...(0, cloud_functions_1.optionsToTrigger)(this.depOpts || {}),
taskQueueTrigger: {},
};
(0, encoding_1.copyIfPresent)(func.__trigger.taskQueueTrigger, this.tqOpts, "retryConfig");
(0, encoding_1.copyIfPresent)(func.__trigger.taskQueueTrigger, this.tqOpts, "rateLimits");
(0, encoding_1.convertIfPresent)(func.__trigger.taskQueueTrigger, this.tqOpts, "invoker", "invoker", encoding_1.convertInvoker);
func.__endpoint = {
platform: "gcfv1",
...(0, manifest_1.initV1Endpoint)(this.depOpts),
...(0, cloud_functions_1.optionsToEndpoint)(this.depOpts),
taskQueueTrigger: (0, manifest_1.initTaskQueueTrigger)(this.depOpts),
};
(0, encoding_1.copyIfPresent)(func.__endpoint.taskQueueTrigger.retryConfig, ((_a = this.tqOpts) === null || _a === void 0 ? void 0 : _a.retryConfig) || {}, "maxAttempts", "maxBackoffSeconds", "maxDoublings", "maxRetrySeconds", "minBackoffSeconds");
(0, encoding_1.copyIfPresent)(func.__endpoint.taskQueueTrigger.rateLimits, ((_b = this.tqOpts) === null || _b === void 0 ? void 0 : _b.rateLimits) || {}, "maxConcurrentDispatches", "maxDispatchesPerSecond");
(0, encoding_1.convertIfPresent)(func.__endpoint.taskQueueTrigger, this.tqOpts, "invoker", "invoker", encoding_1.convertInvoker);
func.__requiredAPIs = [
{
api: "cloudtasks.googleapis.com",
reason: "Needed for task queue functions",
},
];
func.run = handler;
return func;
}
}
exports.TaskQueueBuilder = TaskQueueBuilder;
/**
* Declares a function that can handle tasks enqueued using the Firebase Admin SDK.
* @param options - Configuration for the Task Queue that feeds into this function.
* Omitting options will configure a Task Queue with default settings.
*/
function taskQueue(options) {
return new TaskQueueBuilder(options);
}
exports.taskQueue = taskQueue;

View File

@@ -0,0 +1,184 @@
import { CloudFunction, EventContext } from "../cloud-functions";
/** Handle events related to Test Lab test matrices. */
export declare function testMatrix(): TestMatrixBuilder;
/** Builder used to create Cloud Functions for Test Lab test matrices events. */
export declare class TestMatrixBuilder {
private triggerResource;
private options;
/** Handle a TestMatrix that reached a final test state. */
onComplete(handler: (testMatrix: TestMatrix, context: EventContext) => PromiseLike<any> | any): CloudFunction<TestMatrix>;
}
/** TestMatrix captures details about a test run. */
export declare class TestMatrix {
/** Unique id set by the service. */
testMatrixId: string;
/** When this test matrix was initially created (ISO8601 timestamp). */
createTime: string;
/** Indicates the current progress of the test matrix */
state: TestState;
/**
* The overall outcome of the test matrix run. Only set when the test matrix
* state is FINISHED.
*/
outcomeSummary?: OutcomeSummary;
/** For 'INVALID' matrices only, describes why the matrix is invalid. */
invalidMatrixDetails?: InvalidMatrixDetails;
/** Where the results for the matrix are located. */
resultStorage: ResultStorage;
/** Information about the client which invoked the test. */
clientInfo: ClientInfo;
}
/** Information about the client which invoked the test. */
export declare class ClientInfo {
/** Client name, e.g. 'gcloud'. */
name: string;
/** Map of detailed information about the client which invoked the test. */
details: {
[key: string]: string;
};
}
/** Locations where the test results are stored. */
export declare class ResultStorage {
/** A storage location within Google Cloud Storage (GCS) for the test artifacts. */
gcsPath?: string;
/** Id of the ToolResults History containing these results. */
toolResultsHistoryId?: string;
/**
* Id of the ToolResults execution that the detailed TestMatrix results are
* written to.
*/
toolResultsExecutionId?: string;
/** URL to test results in Firebase Console. */
resultsUrl?: string;
}
/**
* The detailed reason that a Matrix was deemed INVALID.
*
* @remarks
* Possible values:
*
* - `DETAILS_UNAVAILABLE`: The matrix is INVALID, but there are no further details available.
*
* - `MALFORMED_APK`: The input app APK could not be parsed.
*
* - `MALFORMED_TEST_APK`: The input test APK could not be parsed.
*
* - `NO_MANIFEST`: The AndroidManifest.xml could not be found.
*
* - `NO_PACKAGE_NAME`: The APK manifest does not declare a package name.
*
* - `INVALID_PACKAGE_NAME`: The APK application ID is invalid.
*
* - `TEST_SAME_AS_APP`: The test package and app package are the same.
*
* - `NO_INSTRUMENTATION`: The test apk does not declare an instrumentation.
*
* - `NO_SIGNATURE`: The input app apk does not have a signature.
*
* - `INSTRUMENTATION_ORCHESTRATOR_INCOMPATIBLE`: The test runner class specified by
* user or in the test APK`s manifest file is not compatible with Android Test Orchestrator.
*
* - `NO_TEST_RUNNER_CLASS`: The test APK does not contain the test runner class
* specified by user or in the manifest file.
*
* - `NO_LAUNCHER_ACTIVITY`: A main launcher activity could not be found.
*
* - `FORBIDDEN_PERMISSIONS`: The app declares one or more permissions that are
* not allowed.
*
* - `INVALID_ROBO_DIRECTIVES`: There is a conflict in the provided
* robo_directives.
*
* - `INVALID_RESOURCE_NAME`: There is at least one invalid resource name in the
* provided robo directives.
*
* - `INVALID_DIRECTIVE_ACTION`: Invalid definition of action in the robo
* directives, e.g. a click or ignore action includes an input text field.
*
* - `TEST_LOOP_INTENT_FILTER_NOT_FOUND`: There is no test loop intent filter,
* or the one that is given is not formatted correctly.
*
* - `SCENARIO_LABEL_NOT_DECLARED`: The request contains a scenario label that
* was not declared in the manifest.
*
* - `SCENARIO_LABEL_MALFORMED`: There was an error when parsing a label value.
*
* - `SCENARIO_NOT_DECLARED`: The request contains a scenario number that was
* not declared in the manifest.
*
* - `DEVICE_ADMIN_RECEIVER`: Device administrator applications are not allowed.
*
* - `MALFORMED_XC_TEST_ZIP`: The zipped XCTest was malformed. The zip did not ]
* contain a single .xctestrun file and the contents of the
* DerivedData/Build/Products directory.
*
* - `BUILT_FOR_IOS_SIMULATOR`: The zipped XCTest was built for the iOS
* simulator rather than for a physical device.
*
* - `NO_TESTS_IN_XC_TEST_ZIP`: The .xctestrun file did not specify any test
* targets.
*
* - `USE_DESTINATION_ARTIFACTS`: One or more of the test targets defined in the
* .xctestrun file specifies "UseDestinationArtifacts", which is disallowed.
*
* - `TEST_NOT_APP_HOSTED`: XC tests which run on physical devices must have
* "IsAppHostedTestBundle" == "true" in the xctestrun file.
*
* - `PLIST_CANNOT_BE_PARSED`: An Info.plist file in the XCTest zip could not be
* parsed.
*
* - `NO_CODE_APK`: APK contains no code.
*
* - `INVALID_INPUT_APK`: Either the provided input APK path was malformed, the
* APK file does not exist, or the user does not have permission to access the
* APK file.
*
* - `INVALID_APK_PREVIEW_SDK`: APK is built for a preview SDK which is
* unsupported.
*/
export type InvalidMatrixDetails = "DETAILS_UNAVAILABLE" | "MALFORMED_APK" | "MALFORMED_TEST_APK" | "NO_MANIFEST" | "NO_PACKAGE_NAME" | "INVALID_PACKAGE_NAME" | "TEST_SAME_AS_APP" | "NO_INSTRUMENTATION" | "NO_SIGNATURE" | "INSTRUMENTATION_ORCHESTRATOR_INCOMPATIBLE" | "NO_TEST_RUNNER_CLASS" | "NO_LAUNCHER_ACTIVITY" | "FORBIDDEN_PERMISSIONS" | "INVALID_ROBO_DIRECTIVES" | "INVALID_RESOURCE_NAME" | "INVALID_DIRECTIVE_ACTION" | "TEST_LOOP_INTENT_FILTER_NOT_FOUND" | "SCENARIO_LABEL_NOT_DECLARED" | "SCENARIO_LABEL_MALFORMED" | "SCENARIO_NOT_DECLARED" | "DEVICE_ADMIN_RECEIVER" | "MALFORMED_XC_TEST_ZIP" | "BUILT_FOR_IOS_SIMULATOR" | "NO_TESTS_IN_XC_TEST_ZIP" | "USE_DESTINATION_ARTIFACTS" | "TEST_NOT_APP_HOSTED" | "PLIST_CANNOT_BE_PARSED" | "NO_CODE_APK" | "INVALID_INPUT_APK" | "INVALID_APK_PREVIEW_SDK";
/**
* The state (i.e. progress) of a TestMatrix.
*
* @remarks
* Possible values:
*
* - `VALIDATING`: The matrix is being validated.
*
* - `PENDING`: The matrix is waiting for resources to become available.
*
* - `FINISHED`: The matrix has terminated normally. This means that the matrix
* level processing completed normally, but individual executions may be in an
* ERROR state.
*
* - `ERROR`: The matrix has stopped because it encountered an infrastructure
* failure.
*
* - `INVALID`: The matrix was not run because the provided inputs are not
* valid. E.g. the input file is not of the expected type, or is
* malformed/corrupt.
*/
export type TestState = "VALIDATING" | "PENDING" | "FINISHED" | "ERROR" | "INVALID";
/**
* Outcome summary for a finished TestMatrix.
*
* @remarks
* Possible values:
*
* - `SUCCESS`: The test matrix run was successful, for instance:
* - All the test cases passed.
* - Robo did not detect a crash of the application under test.
*
* - `FAILURE`: The test run failed, for instance:
* - One or more test cases failed.
* - A test timed out.
* - The application under test crashed.
*
* - `INCONCLUSIVE`: Something unexpected happened. The run should still be
* considered unsuccessful but this is likely a transient problem and
* re-running the test might be successful.
*
* - `SKIPPED`: All tests were skipped, for instance:
* - All device configurations were incompatible.
*/
export type OutcomeSummary = "SUCCESS" | "FAILURE" | "INCONCLUSIVE" | "SKIPPED";

View File

@@ -0,0 +1,108 @@
"use strict";
// The MIT License (MIT)
//
// Copyright (c) 2019 Firebase
//
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ResultStorage = exports.ClientInfo = exports.TestMatrix = exports.TestMatrixBuilder = exports._testMatrixWithOpts = exports.testMatrix = exports.TEST_MATRIX_COMPLETE_EVENT_TYPE = exports.SERVICE = exports.PROVIDER = void 0;
const cloud_functions_1 = require("../cloud-functions");
/** @internal */
exports.PROVIDER = "google.testing";
/** @internal */
exports.SERVICE = "testing.googleapis.com";
/** @internal */
exports.TEST_MATRIX_COMPLETE_EVENT_TYPE = "testMatrix.complete";
/** Handle events related to Test Lab test matrices. */
function testMatrix() {
return _testMatrixWithOpts({});
}
exports.testMatrix = testMatrix;
/** @internal */
function _testMatrixWithOpts(opts) {
return new TestMatrixBuilder(() => {
if (!process.env.GCLOUD_PROJECT) {
throw new Error("process.env.GCLOUD_PROJECT is not set.");
}
return "projects/" + process.env.GCLOUD_PROJECT + "/testMatrices/{matrix}";
}, opts);
}
exports._testMatrixWithOpts = _testMatrixWithOpts;
/** Builder used to create Cloud Functions for Test Lab test matrices events. */
class TestMatrixBuilder {
/** @internal */
constructor(triggerResource, options) {
this.triggerResource = triggerResource;
this.options = options;
}
/** Handle a TestMatrix that reached a final test state. */
onComplete(handler) {
const dataConstructor = (raw) => {
return new TestMatrix(raw.data);
};
return (0, cloud_functions_1.makeCloudFunction)({
provider: exports.PROVIDER,
eventType: exports.TEST_MATRIX_COMPLETE_EVENT_TYPE,
triggerResource: this.triggerResource,
service: exports.SERVICE,
dataConstructor,
handler,
options: this.options,
});
}
}
exports.TestMatrixBuilder = TestMatrixBuilder;
/** TestMatrix captures details about a test run. */
class TestMatrix {
/** @internal */
constructor(data) {
this.testMatrixId = data.testMatrixId;
this.createTime = data.timestamp;
this.state = data.state;
this.outcomeSummary = data.outcomeSummary;
this.invalidMatrixDetails = data.invalidMatrixDetails;
this.resultStorage = new ResultStorage(data.resultStorage);
this.clientInfo = new ClientInfo(data.clientInfo);
}
}
exports.TestMatrix = TestMatrix;
/** Information about the client which invoked the test. */
class ClientInfo {
/** @internal */
constructor(data) {
this.name = (data === null || data === void 0 ? void 0 : data.name) || "";
this.details = {};
for (const detail of (data === null || data === void 0 ? void 0 : data.clientInfoDetails) || []) {
this.details[detail.key] = detail.value || "";
}
}
}
exports.ClientInfo = ClientInfo;
/** Locations where the test results are stored. */
class ResultStorage {
/** @internal */
constructor(data) {
var _a, _b, _c;
this.gcsPath = (_a = data === null || data === void 0 ? void 0 : data.googleCloudStorage) === null || _a === void 0 ? void 0 : _a.gcsPath;
this.toolResultsHistoryId = (_b = data === null || data === void 0 ? void 0 : data.toolResultsHistory) === null || _b === void 0 ? void 0 : _b.historyId;
this.toolResultsExecutionId = (_c = data === null || data === void 0 ? void 0 : data.toolResultsExecution) === null || _c === void 0 ? void 0 : _c.executionId;
this.resultsUrl = data === null || data === void 0 ? void 0 : data.resultsUrl;
}
}
exports.ResultStorage = ResultStorage;