diff --git a/package.json b/package.json index cc37b3410..3c6ec6776 100644 --- a/package.json +++ b/package.json @@ -26,23 +26,11 @@ "bin": { "firebase-functions": "./lib/bin/firebase-functions.js" }, - "types": "lib/v1/index.d.ts", + "types": "lib/v2/index.d.ts", "exports": { - ".": "./lib/v1/index.js", "./logger/compat": "./lib/logger/compat.js", "./logger": "./lib/logger/index.js", "./params": "./lib/params/index.js", - "./v1": "./lib/v1/index.js", - "./v1/analytics": "./lib/v1/providers/analytics.js", - "./v1/auth": "./lib/v1/providers/auth.js", - "./v1/database": "./lib/v1/providers/database.js", - "./v1/firestore": "./lib/v1/providers/firestore.js", - "./v1/https": "./lib/v1/providers/https.js", - "./v1/pubsub": "./lib/v1/providers/pubsub.js", - "./v1/remoteConfig": "./lib/v1/providers/remoteConfig.js", - "./v1/storage": "./lib/v1/providers/storage.js", - "./v1/tasks": "./lib/v1/providers/tasks.js", - "./v1/testLab": "./lib/v1/providers/testLab.js", "./v2": "./lib/v2/index.js", "./v2/core": "./lib/v2/core.js", "./v2/options": "./lib/v2/options.js", @@ -74,39 +62,6 @@ "params": [ "lib/params" ], - "v1": [ - "lib/v1" - ], - "v1/analytics": [ - "lib/v1/providers/analytics" - ], - "v1/auth": [ - "lib/v1/providers/auth" - ], - "v1/database": [ - "lib/v1/privders/database" - ], - "v1/firestore": [ - "lib/v1/providers/firestore" - ], - "v1/https": [ - "./lib/v1/providers/https" - ], - "v1/pubsub": [ - "lib/v1/providers/pubsub" - ], - "v1/remoteConfig": [ - "lib/v1/providers/remoteConfig" - ], - "v1/storage": [ - "lib/v1/providers/storage" - ], - "v1/tasks": [ - "lib/v1/providers/tasks" - ], - "v1/testLab": [ - "lib/v1/providers/testLab" - ], "v2": [ "lib/v2" ], @@ -253,4 +208,4 @@ "engines": { "node": ">=14.10.0" } -} +} \ No newline at end of file diff --git a/src/common/providers/identity.ts b/src/common/providers/identity.ts index 5e9551bb7..bf2b927d8 100644 --- a/src/common/providers/identity.ts +++ b/src/common/providers/identity.ts @@ -23,13 +23,163 @@ import * as express from "express"; import * as auth from "firebase-admin/auth"; import * as logger from "../../logger"; -import { EventContext } from "../../v1/cloud-functions"; import { getApp } from "../app"; import { isDebugFeatureEnabled } from "../debug"; import { HttpsError, unsafeDecodeToken } from "./https"; export { HttpsError }; +/** + * 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 }; +} + +/** + * 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> { + /** + * 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 event’s 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//events/` + * + * Realtime Database: `projects/_/instances//refs/` + * + * Storage: `projects/_/buckets//objects/#` + * + * Authentication: `projects/` + * + * Pub/Sub: `projects//topics/` + * + * 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; +} + const DISALLOWED_CUSTOM_CLAIMS = [ "acr", "amr", @@ -78,7 +228,7 @@ export type UserInfo = auth.UserInfo; * Helper class to create the user metadata in a `UserRecord` object. */ export class UserRecordMetadata implements auth.UserMetadata { - constructor(public creationTime: string, public lastSignInTime: string) {} + constructor(public creationTime: string, public lastSignInTime: string) { } /** Returns a plain JavaScript object with the properties of UserRecordMetadata. */ toJSON(): AuthUserMetadata { @@ -854,8 +1004,8 @@ export function wrapHandler(eventType: AuthBlockingEventType, handler: HandlerV1 const decodedPayload: DecodedPayload = isDebugFeatureEnabled("skipTokenVerification") ? unsafeDecodeAuthBlockingToken(req.body.data.jwt) : handler.length === 2 - ? await auth.getAuth(getApp())._verifyAuthBlockingToken(req.body.data.jwt) - : await auth.getAuth(getApp())._verifyAuthBlockingToken(req.body.data.jwt, "run.app"); + ? await auth.getAuth(getApp())._verifyAuthBlockingToken(req.body.data.jwt) + : await auth.getAuth(getApp())._verifyAuthBlockingToken(req.body.data.jwt, "run.app"); const authUserRecord = parseAuthUserRecord(decodedPayload.user_record); const authEventContext = parseAuthEventContext(decodedPayload, projectId); diff --git a/src/v1/cloud-functions.ts b/src/v1/cloud-functions.ts deleted file mode 100644 index d5bd3d015..000000000 --- a/src/v1/cloud-functions.ts +++ /dev/null @@ -1,641 +0,0 @@ -// 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. - -import { Request, Response } from "express"; -import { warn } from "../logger"; -import { - DEFAULT_FAILURE_POLICY, - DeploymentOptions, - RESET_VALUE, - FailurePolicy, - Schedule, -} from "./function-configuration"; -export { Request, Response }; -import { - convertIfPresent, - copyIfPresent, - serviceAccountFromShorthand, - durationFromSeconds, -} from "../common/encoding"; -import { - initV1Endpoint, - initV1ScheduleTrigger, - ManifestEndpoint, - ManifestRequiredAPI, -} from "../runtime/manifest"; -import { ResetValue } from "../common/options"; -import { SecretParam } from "../params/types"; -import { withInit } from "../common/onInit"; - -export { Change } from "../common/change"; - -/** @internal */ -const WILDCARD_REGEX = new RegExp("{[^/{}]*}", "g"); - -/** - * 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> { - /** - * 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 event’s 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//events/` - * - * Realtime Database: `projects/_/instances//refs/` - * - * Storage: `projects/_/buckets//objects/#` - * - * Authentication: `projects/` - * - * Pub/Sub: `projects//topics/` - * - * 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; - }; - 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 { - /** Directly invoke the user defined function. */ - run: (data: T, context: any) => PromiseLike | 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; - - /** @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; - - /** @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 extends Runnable { - (input: any, context?: any): PromiseLike | any; - - /** @alpha */ - __trigger: TriggerAnnotation; - - /** @alpha */ - __endpoint: ManifestEndpoint; - - /** @alpha */ - __requiredAPIs?: ManifestRequiredAPI[]; -} - -/** @internal */ -export interface MakeCloudFunctionArgs { - after?: (raw: Event) => void; - before?: (raw: Event) => void; - contextOnlyHandler?: (context: EventContext) => PromiseLike | any; - dataConstructor?: (raw: Event) => EventData; - eventType: string; - handler?: (data: EventData, context: EventContext) => PromiseLike | any; - labels?: Record; - legacyEventType?: string; - options?: DeploymentOptions; - /* - * TODO: should remove `provider` and require a fully qualified `eventType` - * once all providers have migrated to new format. - */ - provider: string; - service: string; - triggerResource: () => string; -} - -/** @internal */ -export function makeCloudFunction({ - contextOnlyHandler, - dataConstructor = (raw: Event) => raw.data, - eventType, - handler, - labels = {}, - legacyEventType, - options = {}, - provider, - service, - triggerResource, -}: MakeCloudFunctionArgs): CloudFunction { - const cloudFunction: any = (data: any, context: any) => { - 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: 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); - } - - handler = withInit(handler); - 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") { - warn("Function returned undefined, expected Promise or value"); - } - return Promise.resolve(promise); - }; - - Object.defineProperty(cloudFunction, "__trigger", { - get: () => { - if (triggerResource() == null) { - return {}; - } - - const trigger: any = { - ...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: ManifestEndpoint = { - platform: "gcfv1", - ...initV1Endpoint(options), - ...optionsToEndpoint(options), - }; - - if (options.schedule) { - endpoint.scheduleTrigger = initV1ScheduleTrigger(options.schedule.schedule, options); - copyIfPresent(endpoint.scheduleTrigger, options.schedule, "timeZone"); - 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; -} - -function _makeParams( - context: EventContext, - triggerResourceGetter: () => string -): Record { - 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: { [option: string]: any } = {}; - - // Note: some tests don't set context.resource.name - const eventResourceParts = context?.resource?.name?.split?.("/"); - 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: Event, authType: string) { - if (authType === "UNAUTHENTICATED") { - return null; - } - return { - uid: event.context?.auth?.variable?.uid, - token: event.context?.auth?.variable?.token, - }; -} - -function _detectAuthType(event: Event) { - if (event.context?.auth?.admin) { - return "ADMIN"; - } - if (event.context?.auth?.variable) { - return "USER"; - } - return "UNAUTHENTICATED"; -} - -/** @hidden */ -export function optionsToTrigger(options: DeploymentOptions) { - const trigger: any = {}; - copyIfPresent( - trigger, - options, - "regions", - "schedule", - "minInstances", - "maxInstances", - "ingressSettings", - "vpcConnectorEgressSettings", - "vpcConnector", - "labels", - "secrets" - ); - convertIfPresent(trigger, options, "failurePolicy", "failurePolicy", (policy) => { - if (policy === false) { - return undefined; - } else if (policy === true) { - return DEFAULT_FAILURE_POLICY; - } else { - return policy; - } - }); - convertIfPresent(trigger, options, "timeout", "timeoutSeconds", durationFromSeconds); - 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]; - }); - convertIfPresent( - trigger, - options, - "serviceAccountEmail", - "serviceAccount", - serviceAccountFromShorthand - ); - - return trigger; -} - -export function optionsToEndpoint(options: DeploymentOptions): ManifestEndpoint { - const endpoint: ManifestEndpoint = {}; - copyIfPresent( - endpoint, - options, - "omit", - "minInstances", - "maxInstances", - "ingressSettings", - "labels", - "timeoutSeconds" - ); - convertIfPresent(endpoint, options, "region", "regions"); - convertIfPresent(endpoint, options, "serviceAccountEmail", "serviceAccount", (sa) => sa); - convertIfPresent( - endpoint, - options, - "secretEnvironmentVariables", - "secrets", - (secrets: (string | SecretParam)[]) => - secrets.map((secret) => ({ key: secret instanceof SecretParam ? secret.name : secret })) - ); - if (options?.vpcConnector !== undefined) { - if (options.vpcConnector === null || options.vpcConnector instanceof ResetValue) { - endpoint.vpc = RESET_VALUE; - } else { - const vpc: ManifestEndpoint["vpc"] = { connector: options.vpcConnector }; - convertIfPresent(vpc, options, "egressSettings", "vpcConnectorEgressSettings"); - endpoint.vpc = vpc; - } - } - 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; -} diff --git a/src/v1/config.ts b/src/v1/config.ts deleted file mode 100644 index 7821b59d7..000000000 --- a/src/v1/config.ts +++ /dev/null @@ -1,80 +0,0 @@ -// 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. - -import * as fs from "fs"; -import * as path from "path"; - -export { firebaseConfig } from "../common/config"; - -/** @internal */ -export let singleton: Record; - -/** @internal */ -export function resetCache(): void { - singleton = undefined; -} - -/** - * 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 - * [Environment Configuration](/docs/functions/config-env). - */ -export function config(): Record { - // 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 singleton === "undefined") { - init(); - } - return singleton; -} - -function init() { - try { - const parsed = JSON.parse(process.env.CLOUD_RUNTIME_CONFIG); - delete parsed.firebase; - 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; - singleton = parsed; - return; - } catch (e) { - // Do nothing - } - - singleton = {}; -} diff --git a/src/v1/function-builder.ts b/src/v1/function-builder.ts deleted file mode 100644 index e70f26166..000000000 --- a/src/v1/function-builder.ts +++ /dev/null @@ -1,501 +0,0 @@ -// 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. - -import * as express from "express"; - -import { ResetValue } from "../common/options"; -import { Expression, SecretParam } from "../params/types"; -import { EventContext } from "./cloud-functions"; -import { - DeploymentOptions, - INGRESS_SETTINGS_OPTIONS, - MAX_NUMBER_USER_LABELS, - MAX_TIMEOUT_SECONDS, - RuntimeOptions, - SUPPORTED_REGIONS, - VALID_MEMORY_OPTIONS, - VPC_EGRESS_SETTINGS_OPTIONS, -} 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"; - -/** - * 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: RuntimeOptions): boolean { - const mem = runtimeOptions.memory; - if (mem && typeof mem !== "object" && !VALID_MEMORY_OPTIONS.includes(mem)) { - throw new Error( - `The only valid memory allocation values are: ${VALID_MEMORY_OPTIONS.join(", ")}` - ); - } - if ( - typeof runtimeOptions.timeoutSeconds === "number" && - (runtimeOptions.timeoutSeconds > MAX_TIMEOUT_SECONDS || runtimeOptions.timeoutSeconds < 0) - ) { - throw new Error(`TimeoutSeconds must be between 0 and ${MAX_TIMEOUT_SECONDS}`); - } - - if ( - runtimeOptions.ingressSettings && - !(runtimeOptions.ingressSettings instanceof ResetValue) && - !INGRESS_SETTINGS_OPTIONS.includes(runtimeOptions.ingressSettings) - ) { - throw new Error( - `The only valid ingressSettings values are: ${INGRESS_SETTINGS_OPTIONS.join(",")}` - ); - } - - if ( - runtimeOptions.vpcConnectorEgressSettings && - !(runtimeOptions.vpcConnectorEgressSettings instanceof ResetValue) && - !VPC_EGRESS_SETTINGS_OPTIONS.includes(runtimeOptions.vpcConnectorEgressSettings) - ) { - throw new Error( - `The only valid vpcConnectorEgressSettings values are: ${VPC_EGRESS_SETTINGS_OPTIONS.join( - "," - )}` - ); - } - - validateFailurePolicy(runtimeOptions.failurePolicy); - const serviceAccount = runtimeOptions.serviceAccount; - if ( - serviceAccount && - !( - serviceAccount === "default" || - serviceAccount instanceof ResetValue || - serviceAccount instanceof 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 > MAX_NUMBER_USER_LABELS) { - throw new Error( - `A function must not have more than ${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 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: any) { - 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: (string | Expression | ResetValue)[]): boolean { - 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') - */ -export function region( - ...regions: Array<(typeof SUPPORTED_REGIONS)[number] | string | Expression | ResetValue> -): FunctionBuilder { - if (assertRegionsAreValid(regions)) { - return new FunctionBuilder({ regions }); - } -} - -/** - * 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 function runWith(runtimeOptions: RuntimeOptions): FunctionBuilder { - if (assertRuntimeOptionsValid(runtimeOptions)) { - return new FunctionBuilder(runtimeOptions); - } -} - -export class FunctionBuilder { - constructor(private 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 | ResetValue> - ): FunctionBuilder { - 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: RuntimeOptions): FunctionBuilder { - 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: (req: https.Request, resp: express.Response) => void | Promise) => - 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: (data: any, context: https.CallableContext) => any | Promise) => - 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?: tasks.TaskQueueOptions) => { - 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: string) => 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: Ref) => 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: Path) => - firestore._documentWithOptions(path, this.options), - - /** @hidden */ - namespace: (namespace: string) => firestore._namespaceWithOptions(namespace, this.options), - - /** @hidden */ - database: (database: string) => 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: string) => - 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: ( - version: remoteConfig.TemplateVersion, - context: EventContext - ) => PromiseLike | any - ) => 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?: string) => 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: string) => pubsub._topicWithOptions(topic, this.options), - schedule: (schedule: string) => pubsub._scheduleWithOptions(schedule, this.options), - }; - } - - get auth() { - return { - /** - * Handle events related to Firebase authentication users. - */ - user: (userOptions?: auth.UserOptions) => auth._userWithOptions(this.options, userOptions), - }; - } - - get testLab() { - return { - /** - * Handle events related to Test Lab test matrices. - */ - testMatrix: () => testLab._testMatrixWithOpts(this.options), - }; - } -} diff --git a/src/v1/function-configuration.ts b/src/v1/function-configuration.ts deleted file mode 100644 index 90aa391fc..000000000 --- a/src/v1/function-configuration.ts +++ /dev/null @@ -1,303 +0,0 @@ -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 const 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", -] as const; - -/** - * Cloud Functions min timeout value. - */ -export const MIN_TIMEOUT_SECONDS = 0; - -/** - * Cloud Functions max timeout value. - */ -export const MAX_TIMEOUT_SECONDS = 540; - -/** - * List of available memory options supported by Cloud Functions. - */ -export const VALID_MEMORY_OPTIONS = [ - "128MB", - "256MB", - "512MB", - "1GB", - "2GB", - "4GB", - "8GB", -] as const; - -/** - * List of available options for VpcConnectorEgressSettings. - */ -export const VPC_EGRESS_SETTINGS_OPTIONS = [ - "VPC_CONNECTOR_EGRESS_SETTINGS_UNSPECIFIED", - "PRIVATE_RANGES_ONLY", - "ALL_TRAFFIC", -] as const; - -/** - * List of available options for IngressSettings. - */ -export const INGRESS_SETTINGS_OPTIONS = [ - "INGRESS_SETTINGS_UNSPECIFIED", - "ALLOW_ALL", - "ALLOW_INTERNAL_ONLY", - "ALLOW_INTERNAL_AND_GCLB", -] as const; - -/** - * 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 | 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 | ResetValue; - /** - * The minimum amount of time to wait before retrying a job after it fails. - * - * @defaultValue 5 seconds - */ - minBackoffDuration?: string | Expression | ResetValue; - /** - * The maximum amount of time to wait before retrying a job after it fails. - * - * @defaultValue 1 hour - */ - maxBackoffDuration?: string | Expression | ResetValue; - /** - * The max number of backoff doubling applied at each retry. - * - * @defaultValue 5 - */ - maxDoublings?: number | Expression | 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; -} - -export const DEFAULT_FAILURE_POLICY: FailurePolicy = { - retry: {}, -}; - -export const MAX_NUMBER_USER_LABELS = 58; - -/** - * Configuration options for a function that applicable at runtime. - */ -export interface RuntimeOptions { - /** - * Which platform should host the backend. Valid options are "gcfv1" - * @internal - */ - platform?: "gcfv1"; - - /** - * 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 | ResetValue; - /** - * Timeout for the function in seconds, possible values are 0 to 540. - */ - timeoutSeconds?: number | Expression | 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 | ResetValue; - - /** - * Max number of actual instances allowed to be running in parallel. - */ - maxInstances?: number | Expression | ResetValue; - - /** - * Connect cloud function to specified VPC connector. - */ - vpcConnector?: string | Expression | 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 | 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; - - /** - * Invoker to set access control on https functions. - */ - invoker?: "public" | "private" | string | string[]; - - /* - * Secrets to bind to a function instance. - */ - 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; - /** - * Regions where function should be deployed. - */ - regions?: Array<(typeof SUPPORTED_REGIONS)[number] | string | Expression | ResetValue>; - /** - * Schedule for the scheduled function. - */ - schedule?: Schedule; -} diff --git a/src/v1/index.ts b/src/v1/index.ts deleted file mode 100644 index 7f3f9e10b..000000000 --- a/src/v1/index.ts +++ /dev/null @@ -1,63 +0,0 @@ -// 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. - -// Providers: -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 const app = { setEmulatedAdminApp }; - -// Exported root types: -export * from "./cloud-functions"; -export * from "./config"; -export * from "./function-builder"; -export * from "./function-configuration"; -// NOTE: Equivalent to `export * as params from "../params"` but api-extractor doesn't support that syntax. -import * as params from "../params"; -export { params }; - -export { onInit } from "../common/onInit"; diff --git a/src/v1/providers/analytics.ts b/src/v1/providers/analytics.ts deleted file mode 100644 index 63895a7ca..000000000 --- a/src/v1/providers/analytics.ts +++ /dev/null @@ -1,513 +0,0 @@ -// 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. - -import { CloudFunction, Event, EventContext, makeCloudFunction } from "../cloud-functions"; -import { DeploymentOptions } from "../function-configuration"; - -/** @internal */ -export const provider = "google.analytics"; -/** @internal */ -export const 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. - */ -export function event(analyticsEventType: string) { - return _eventWithOptions(analyticsEventType, {}); -} - -/** @internal */ -export function _eventWithOptions(analyticsEventType: string, options: DeploymentOptions) { - 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); -} - -/** - * The Firebase Analytics event builder interface. - * - * Access via `functions.analytics.event()`. - */ -export class AnalyticsEventBuilder { - /** @hidden */ - constructor(private triggerResource: () => string, private 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 - ): CloudFunction { - const dataConstructor = (raw: Event) => { - return new AnalyticsEvent(raw.data); - }; - return makeCloudFunction({ - handler, - provider, - eventType: "event.log", - service, - legacyEventType: `providers/google.firebase.analytics/eventTypes/event.log`, - triggerResource: this.triggerResource, - dataConstructor, - options: this.options, - }); - } -} - -/** Interface representing a Firebase Analytics event that was logged for a specific user. */ -export 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) { - 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)); - } -} - -/** - * Interface representing the user who triggered the events. - */ -export class UserDimensions { - /* tslint:disable:max-line-length */ - /** - * 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; - /* tslint:enable:max-line-length */ - - /** 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) { - // 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) as any); - - // 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 */ - } -} - -/** Predefined or custom properties stored on the client side. */ -export 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) { - copyField(wireFormat, this, "value", unwrapValueAsString as any); - copyTimestampToString(wireFormat, this, "setTimestampUsec", "setTime"); - } -} - -/** - * 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 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) { - copyField(wireFormat, this, "bundleSequenceId"); - copyTimestampToMillis(wireFormat, this, "serverTimestampOffsetMicros", "serverTimestampOffset"); - } -} - -/** @hidden */ -function copyFieldTo( - from: From, - to: To, - fromField: FromKey, - toField: ToKey, - transform?: (val: Required[FromKey]) => Required[ToKey] -): void { - if (typeof from[fromField] === "undefined") { - return; - } - if (transform) { - to[toField] = transform(from[fromField]); - return; - } - to[toField] = from[fromField] as any; -} - -/** @hidden */ -function copyField( - from: From, - to: To, - field: Key, - transform: (val: Required[Key]) => Required[Key] = (from) => from as any -): void { - copyFieldTo(from, to, field, field, transform); -} - -/** @hidden */ -function copyFields( - from: From, - to: To, - fields: Key[] -): void { - for (const field of fields) { - copyField(from, to, field); - } -} - -type TransformedObject any> = { - [key in keyof Obj]: ReturnType; -}; -function mapKeys any>( - obj: Obj, - transform: Transform -): TransformedObject { - 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: any): string { - const key: string = 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: any): any { - const key: string = Object.keys(wrapped)[0]; - const value: string = 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: any, - to: T, - fromName: string, - toName: K -) { - if (from[fromName] !== undefined) { - to[toName] = Math.round(from[fromName] / 1000) as any; - } -} - -// 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: any, - to: T, - fromName: string, - toName: K -) { - if (from[fromName] !== undefined) { - to[toName] = new Date(from[fromName] / 1000).toISOString() as any; - } -} diff --git a/src/v1/providers/auth.ts b/src/v1/providers/auth.ts deleted file mode 100644 index edef7b0bb..000000000 --- a/src/v1/providers/auth.ts +++ /dev/null @@ -1,256 +0,0 @@ -// 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. - -import { - AuthBlockingEventType, - AuthEventContext, - AuthUserRecord, - BeforeCreateResponse, - BeforeSignInResponse, - HttpsError, - UserInfo, - UserRecord, - userRecordConstructor, - UserRecordMetadata, - wrapHandler, -} from "../../common/providers/identity"; -import { - BlockingFunction, - CloudFunction, - Event, - EventContext, - makeCloudFunction, - optionsToEndpoint, - optionsToTrigger, -} from "../cloud-functions"; -import { DeploymentOptions } from "../function-configuration"; -import { initV1Endpoint } from "../../runtime/manifest"; - -// TODO: yank in next breaking change release -export { UserRecord, UserInfo, UserRecordMetadata, userRecordConstructor }; - -export { HttpsError }; - -/** @internal */ -export const provider = "google.firebase.auth"; -/** @internal */ -export const service = "firebaseauth.googleapis.com"; - -/** - * 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 function user(userOptions?: UserOptions): UserBuilder { - return _userWithOptions({}, userOptions || {}); -} - -/** @internal */ -export function _userWithOptions(options: DeploymentOptions, userOptions: 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 - ); -} - -/** - * Builder used to create functions for Firebase Auth user lifecycle events. - * @public - */ -export class UserBuilder { - private static dataConstructor(raw: Event): UserRecord { - return userRecordConstructor(raw.data); - } - - /* @internal */ - constructor( - private triggerResource: () => string, - private options: DeploymentOptions, - private 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: (user: UserRecord, context: EventContext) => PromiseLike | any - ): CloudFunction { - 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: (user: UserRecord, context: EventContext) => PromiseLike | any - ): CloudFunction { - 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: ( - user: AuthUserRecord, - context: AuthEventContext - ) => BeforeCreateResponse | void | Promise | Promise - ): BlockingFunction { - 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: ( - user: AuthUserRecord, - context: AuthEventContext - ) => BeforeSignInResponse | void | Promise | Promise - ): BlockingFunction { - return this.beforeOperation(handler, "beforeSignIn"); - } - - private onOperation( - handler: (user: UserRecord, context: EventContext) => PromiseLike | any, - eventType: string - ): CloudFunction { - return makeCloudFunction({ - handler, - provider, - eventType, - service, - triggerResource: this.triggerResource, - // eslint-disable-next-line @typescript-eslint/unbound-method - dataConstructor: UserBuilder.dataConstructor, - legacyEventType: `providers/firebase.auth/eventTypes/${eventType}`, - options: this.options, - }); - } - - private beforeOperation( - handler: ( - user: AuthUserRecord, - context: AuthEventContext - ) => - | BeforeCreateResponse - | BeforeSignInResponse - | void - | Promise - | Promise - | Promise, - eventType: AuthBlockingEventType - ): BlockingFunction { - const accessToken = this.userOptions?.blockingOptions?.accessToken || false; - const idToken = this.userOptions?.blockingOptions?.idToken || false; - const refreshToken = this.userOptions?.blockingOptions?.refreshToken || false; - - // Create our own function that just calls the provided function so we know for sure that - // handler takes two arguments. This is something common/providers/identity depends on. - const wrappedHandler = (user: AuthUserRecord, context: AuthEventContext) => - handler(user, context); - const func: any = wrapHandler(eventType, wrappedHandler); - - const legacyEventType = `providers/cloud.auth/eventTypes/user.${eventType}`; - - func.__trigger = { - labels: {}, - ...optionsToTrigger(this.options), - blockingTrigger: { - eventType: legacyEventType, - options: { - accessToken, - idToken, - refreshToken, - }, - }, - }; - - func.__endpoint = { - platform: "gcfv1", - labels: {}, - ...initV1Endpoint(this.options), - ...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; - } -} diff --git a/src/v1/providers/database.ts b/src/v1/providers/database.ts deleted file mode 100644 index d59d7de19..000000000 --- a/src/v1/providers/database.ts +++ /dev/null @@ -1,323 +0,0 @@ -// 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. - -import { getApp } from "../../common/app"; -import { Change } from "../../common/change"; -import { firebaseConfig } from "../../common/config"; -import { ParamsOf } from "../../common/params"; -import { DataSnapshot } from "../../common/providers/database"; -import { normalizePath } from "../../common/utilities/path"; -import { applyChange } from "../../common/utilities/utils"; -import { CloudFunction, Event, EventContext, makeCloudFunction } from "../cloud-functions"; -import { DeploymentOptions } from "../function-configuration"; - -export { DataSnapshot }; - -/** @internal */ -export const provider = "google.firebase.database"; -/** @internal */ -export const 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. - */ -export function instance(instance: string) { - return _instanceWithOptions(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. - */ -export function ref(path: Ref) { - return _refWithOptions(path, {}); -} - -/** @internal */ -export function _instanceWithOptions( - instance: string, - options: DeploymentOptions -): InstanceBuilder { - return new InstanceBuilder(instance, options); -} - -/** - * The Firebase Realtime Database instance builder interface. - * - * Access via [`database.instance()`](providers_database_.html#instance). - */ -export class InstanceBuilder { - constructor(private instance: string, private options: DeploymentOptions) {} - - /** - * @returns Firebase Realtime Database reference builder interface. - */ - ref(path: Ref): RefBuilder { - const normalized = normalizePath(path); - return new RefBuilder( - () => `projects/_/instances/${this.instance}/refs/${normalized}`, - this.options - ); - } -} - -/** @internal */ -export function _refWithOptions( - path: Ref, - options: DeploymentOptions -): RefBuilder { - const resourceGetter = () => { - const normalized = normalizePath(path); - const databaseURL = firebaseConfig().databaseURL; - if (!databaseURL) { - throw new Error( - "Missing expected firebase config value databaseURL, " + - "config is actually" + - JSON.stringify(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); -} - -/** - * The Firebase Realtime Database reference builder interface. - * - * Access via [`functions.database.ref()`](functions.database#.ref). - */ -export class RefBuilder { - constructor(private triggerResource: () => string, private 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, - context: EventContext> - ) => PromiseLike | any - ): CloudFunction> { - 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: ( - change: Change, - context: EventContext> - ) => PromiseLike | any - ): CloudFunction> { - 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: ( - snapshot: DataSnapshot, - context: EventContext> - ) => PromiseLike | any - ): CloudFunction { - const dataConstructor = (raw: Event) => { - const [dbInstance, path] = extractInstanceAndPath( - raw.context.resource.name, - raw.context.domain - ); - return new DataSnapshot(raw.data.delta, path, 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: ( - snapshot: DataSnapshot, - context: EventContext> - ) => PromiseLike | any - ): CloudFunction { - const dataConstructor = (raw: Event) => { - const [dbInstance, path] = extractInstanceAndPath( - raw.context.resource.name, - raw.context.domain - ); - return new DataSnapshot(raw.data.data, path, getApp(), dbInstance); - }; - return this.onOperation(handler, "ref.delete", dataConstructor); - } - - private onOperation( - handler: (data: T, context: EventContext) => PromiseLike | any, - eventType: string, - dataConstructor: (raw: Event | Event) => any - ): CloudFunction { - return makeCloudFunction({ - handler, - provider, - service, - eventType, - legacyEventType: `providers/${provider}/eventTypes/${eventType}`, - triggerResource: this.triggerResource, - dataConstructor, - options: this.options, - }); - } - - private changeConstructor = (raw: Event): Change => { - const [dbInstance, path] = extractInstanceAndPath( - raw.context.resource.name, - raw.context.domain - ); - const before = new DataSnapshot(raw.data.data, path, getApp(), dbInstance); - const after = new DataSnapshot( - applyChange(raw.data.data, raw.data.delta), - path, - getApp(), - dbInstance - ); - return { - before, - after, - }; - }; -} - -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 - */ -export function extractInstanceAndPath(resource: string, 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]; - } -} diff --git a/src/v1/providers/firestore.ts b/src/v1/providers/firestore.ts deleted file mode 100644 index 00ee71114..000000000 --- a/src/v1/providers/firestore.ts +++ /dev/null @@ -1,207 +0,0 @@ -// 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. - -import * as firestore from "firebase-admin/firestore"; - -import { posix } from "path"; -import { Change } from "../../common/change"; -import { ParamsOf } from "../../common/params"; -import { - createBeforeSnapshotFromJson, - createSnapshotFromJson, -} from "../../common/providers/firestore"; -import { CloudFunction, Event, EventContext, makeCloudFunction } from "../cloud-functions"; -import { DeploymentOptions } from "../function-configuration"; - -/** @internal */ -export const provider = "google.firestore"; -/** @internal */ -export const service = "firestore.googleapis.com"; -/** @internal */ -export const defaultDatabase = "(default)"; - -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 function document(path: Path) { - return _documentWithOptions(path, {}); -} - -// Multiple namespaces are not yet supported by Firestore. -export function namespace(namespace: string) { - return _namespaceWithOptions(namespace, {}); -} - -// Multiple databases are not yet supported by Firestore. -export function database(database: string) { - return _databaseWithOptions(database, {}); -} - -/** @internal */ -export function _databaseWithOptions( - database: string = defaultDatabase, - options: DeploymentOptions -) { - return new DatabaseBuilder(database, options); -} - -/** @internal */ -export function _namespaceWithOptions(namespace: string, options: DeploymentOptions) { - return _databaseWithOptions(defaultDatabase, options).namespace(namespace); -} - -/** @internal */ -export function _documentWithOptions(path: Path, options: DeploymentOptions) { - return _databaseWithOptions(defaultDatabase, options).document(path); -} - -export class DatabaseBuilder { - constructor(private database: string, private options: DeploymentOptions) {} - - namespace(namespace: string) { - return new NamespaceBuilder(this.database, this.options, namespace); - } - - document(path: Path) { - return new NamespaceBuilder(this.database, this.options).document(path); - } -} - -export class NamespaceBuilder { - constructor( - private database: string, - private options: DeploymentOptions, - private namespace?: string - ) {} - - document(path: Path) { - return new DocumentBuilder(() => { - if (!process.env.GCLOUD_PROJECT) { - throw new Error("process.env.GCLOUD_PROJECT is not set."); - } - const database = posix.join( - "projects", - process.env.GCLOUD_PROJECT, - "databases", - this.database - ); - return posix.join( - database, - this.namespace ? `documents@${this.namespace}` : "documents", - path - ); - }, this.options); - } -} - -export function snapshotConstructor(event: Event): DocumentSnapshot { - return createSnapshotFromJson( - event.data, - event.context.resource.name, - event?.data?.value?.readTime, - event?.data?.value?.updateTime - ); -} - -// TODO remove this function when wire format changes to new format -export function beforeSnapshotConstructor(event: Event): DocumentSnapshot { - return createBeforeSnapshotFromJson( - event.data, - event.context.resource.name, - event?.data?.oldValue?.readTime, - undefined - ); -} - -function changeConstructor(raw: Event) { - return Change.fromObjects(beforeSnapshotConstructor(raw), snapshotConstructor(raw)); -} - -export class DocumentBuilder { - constructor(private triggerResource: () => string, private options: DeploymentOptions) { - // TODO what validation do we want to do here? - } - - /** Respond to all document writes (creates, updates, or deletes). */ - onWrite( - handler: ( - change: Change, - context: EventContext> - ) => PromiseLike | any - ): CloudFunction> { - return this.onOperation(handler, "document.write", changeConstructor); - } - - /** Respond only to document updates. */ - onUpdate( - handler: ( - change: Change, - context: EventContext> - ) => PromiseLike | any - ): CloudFunction> { - return this.onOperation(handler, "document.update", changeConstructor); - } - - /** Respond only to document creations. */ - onCreate( - handler: ( - snapshot: QueryDocumentSnapshot, - context: EventContext> - ) => PromiseLike | any - ): CloudFunction { - return this.onOperation(handler, "document.create", snapshotConstructor); - } - - /** Respond only to document deletions. */ - onDelete( - handler: ( - snapshot: QueryDocumentSnapshot, - context: EventContext> - ) => PromiseLike | any - ): CloudFunction { - return this.onOperation(handler, "document.delete", beforeSnapshotConstructor); - } - - private onOperation( - handler: (data: T, context: EventContext>) => PromiseLike | any, - eventType: string, - dataConstructor: (raw: Event) => any - ): CloudFunction { - return makeCloudFunction({ - handler, - provider: provider, - eventType, - service: service, - triggerResource: this.triggerResource, - legacyEventType: `providers/cloud.firestore/eventTypes/${eventType}`, - dataConstructor, - options: this.options, - }); - } -} diff --git a/src/v1/providers/https.ts b/src/v1/providers/https.ts deleted file mode 100644 index e9cd5d132..000000000 --- a/src/v1/providers/https.ts +++ /dev/null @@ -1,140 +0,0 @@ -// 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. - -import * as express from "express"; - -import { convertIfPresent, convertInvoker } from "../../common/encoding"; -import { - CallableContext, - FunctionsErrorCode, - HttpsError, - onCallHandler, - Request, -} from "../../common/providers/https"; -import { HttpsFunction, optionsToEndpoint, optionsToTrigger, Runnable } from "../cloud-functions"; -import { DeploymentOptions } from "../function-configuration"; -import { initV1Endpoint } from "../../runtime/manifest"; -import { withInit } from "../../common/onInit"; -import { wrapTraceContext } from "../../v2/trace"; - -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 function onRequest( - handler: (req: Request, resp: express.Response) => void | Promise -): HttpsFunction { - return _onRequestWithOptions(handler, {}); -} - -/** - * 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 function onCall( - handler: (data: any, context: CallableContext) => any | Promise -): HttpsFunction & Runnable { - return _onCallWithOptions(handler, {}); -} - -/** @internal */ -export function _onRequestWithOptions( - handler: (req: Request, resp: express.Response) => void | Promise, - options: DeploymentOptions -): HttpsFunction { - // lets us add __endpoint without altering handler: - const cloudFunction: any = (req: Request, res: express.Response) => { - return wrapTraceContext(withInit(handler))(req, res); - }; - cloudFunction.__trigger = { - ...optionsToTrigger(options), - httpsTrigger: {}, - }; - convertIfPresent( - cloudFunction.__trigger.httpsTrigger, - options, - "invoker", - "invoker", - convertInvoker - ); - // TODO parse the options - - cloudFunction.__endpoint = { - platform: "gcfv1", - ...initV1Endpoint(options), - ...optionsToEndpoint(options), - httpsTrigger: {}, - }; - convertIfPresent( - cloudFunction.__endpoint.httpsTrigger, - options, - "invoker", - "invoker", - convertInvoker - ); - return cloudFunction; -} - -/** @internal */ -export function _onCallWithOptions( - handler: (data: any, context: CallableContext) => any | Promise, - options: DeploymentOptions -): HttpsFunction & Runnable { - // onCallHandler 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: any, context: CallableContext) => { - return withInit(handler)(data, context); - }; - const func: any = wrapTraceContext( - onCallHandler( - { - enforceAppCheck: options.enforceAppCheck, - consumeAppCheckToken: options.consumeAppCheckToken, - cors: { origin: true, methods: "POST" }, - }, - fixedLen - ) - ); - - func.__trigger = { - labels: {}, - ...optionsToTrigger(options), - httpsTrigger: {}, - }; - func.__trigger.labels["deployment-callable"] = "true"; - - func.__endpoint = { - platform: "gcfv1", - labels: {}, - ...initV1Endpoint(options), - ...optionsToEndpoint(options), - callableTrigger: {}, - }; - - func.run = fixedLen; - - return func; -} diff --git a/src/v1/providers/pubsub.ts b/src/v1/providers/pubsub.ts deleted file mode 100644 index 57a28803c..000000000 --- a/src/v1/providers/pubsub.ts +++ /dev/null @@ -1,206 +0,0 @@ -// 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. - -import { CloudFunction, EventContext, makeCloudFunction } from "../cloud-functions"; -import { DeploymentOptions, ScheduleRetryConfig } from "../function-configuration"; - -/** @internal */ -export const provider = "google.pubsub"; -/** @internal */ -export const 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. - */ -export function topic(topic: string) { - return _topicWithOptions(topic, {}); -} - -/** @internal */ -export function _topicWithOptions(topic: string, options: DeploymentOptions): TopicBuilder { - 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); -} - -/** - * The Google Cloud Pub/Sub topic builder. - * - * Access via `functions.pubsub.topic()`. - */ -export class TopicBuilder { - /** @hidden */ - constructor(private triggerResource: () => string, private 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 - ): CloudFunction { - return makeCloudFunction({ - handler, - provider, - service, - triggerResource: this.triggerResource, - eventType: "topic.publish", - dataConstructor: (raw) => new Message(raw.data), - options: this.options, - }); - } -} - -/** - * Registers a Cloud Function to run at specified times. - * - * @param schedule - The schedule, in Unix Crontab or AppEngine syntax. - * @returns ScheduleBuilder interface. - */ -export function schedule(schedule: string): ScheduleBuilder { - return _scheduleWithOptions(schedule, {}); -} - -/** @internal */ -export function _scheduleWithOptions( - schedule: string, - options: DeploymentOptions -): ScheduleBuilder { - 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 }, - }); -} - -/** - * 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 class ScheduleBuilder { - /** @hidden */ - constructor(private triggerResource: () => string, private options: DeploymentOptions) {} - - retryConfig(config: ScheduleRetryConfig): ScheduleBuilder { - this.options.schedule.retryConfig = config; - return this; - } - - timeZone(timeZone: string): ScheduleBuilder { - 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: (context: EventContext) => PromiseLike | any) { - const cloudFunction = makeCloudFunction({ - contextOnlyHandler: handler, - provider, - service, - triggerResource: this.triggerResource, - eventType: "topic.publish", - options: this.options, - labels: { "deployment-scheduled": "true" }, - }); - return cloudFunction; - } -} - -/** - * Interface representing a Google Cloud Pub/Sub message. - * - * @param data - Payload of a Pub/Sub message. - */ -export 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: any; - - constructor(data: any) { - [this.data, this.attributes, this._json] = [data.data, data.attributes || {}, data.json]; - } - - /** - * The JSON data payload of this message object, if any. - */ - get json(): any { - 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(): any { - return { - data: this.data, - attributes: this.attributes, - }; - } -} diff --git a/src/v1/providers/remoteConfig.ts b/src/v1/providers/remoteConfig.ts deleted file mode 100644 index cf67383dc..000000000 --- a/src/v1/providers/remoteConfig.ts +++ /dev/null @@ -1,141 +0,0 @@ -// 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. - -import { CloudFunction, EventContext, makeCloudFunction } from "../cloud-functions"; -import { DeploymentOptions } from "../function-configuration"; - -/** @internal */ -export const provider = "google.firebase.remoteconfig"; -/** @internal */ -export const 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. - */ -export function onUpdate( - handler: (version: TemplateVersion, context: EventContext) => PromiseLike | any -): CloudFunction { - return _onUpdateWithOptions(handler, {}); -} - -/** @internal */ -export function _onUpdateWithOptions( - handler: (version: TemplateVersion, context: EventContext) => PromiseLike | any, - options: DeploymentOptions -): CloudFunction { - 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); -} - -/** Builder used to create Cloud Functions for Remote Config. */ -export class UpdateBuilder { - /** @internal */ - constructor(private triggerResource: () => string, private options: DeploymentOptions) {} - - /** - * 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 - ): CloudFunction { - return makeCloudFunction({ - handler, - provider, - service, - triggerResource: this.triggerResource, - eventType: "update", - options: this.options, - }); - } -} - -/** - * 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; -} diff --git a/src/v1/providers/storage.ts b/src/v1/providers/storage.ts deleted file mode 100644 index 998760eb6..000000000 --- a/src/v1/providers/storage.ts +++ /dev/null @@ -1,343 +0,0 @@ -// 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. - -import { firebaseConfig } from "../../common/config"; -import { CloudFunction, EventContext, makeCloudFunction } from "../cloud-functions"; -import { DeploymentOptions } from "../function-configuration"; - -/** @internal */ -export const provider = "google.storage"; -/** @internal */ -export const 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. - */ -export function bucket(bucket?: string) { - return _bucketWithOptions({}, bucket); -} - -/** - * Registers a Cloud Function scoped to the default storage bucket for the - * project. - * - * @returns Storage object builder interface. - */ -export function object() { - return _objectWithOptions({}); -} - -/** @internal */ -export function _bucketWithOptions(options: DeploymentOptions, bucket?: string): BucketBuilder { - const resourceGetter = () => { - bucket = bucket || 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); -} - -/** @internal */ -export function _objectWithOptions(options: DeploymentOptions): ObjectBuilder { - return _bucketWithOptions(options).object(); -} - -/** - * The Google Cloud Storage bucket builder interface. - * - * Access via `functions.storage.bucket()`. - */ -export class BucketBuilder { - /** @internal */ - constructor(private triggerResource: () => string, private options: DeploymentOptions) {} - - /** - * 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); - } -} - -/** - * The Google Cloud Storage object builder interface. - * - * Access via `functions.storage.object()`. - */ -export class ObjectBuilder { - /** @internal */ - constructor(private triggerResource: () => string, private options: DeploymentOptions) {} - - /** - * 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 - ): CloudFunction { - 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: (object: ObjectMetadata, context: EventContext) => PromiseLike | any - ): CloudFunction { - 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: (object: ObjectMetadata, context: EventContext) => PromiseLike | any - ): CloudFunction { - 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: (object: ObjectMetadata, context: EventContext) => PromiseLike | any - ): CloudFunction { - return this.onOperation(handler, "object.metadataUpdate"); - } - - /** @hidden */ - private onOperation( - handler: (object: ObjectMetadata, context: EventContext) => PromiseLike | any, - eventType: string - ): CloudFunction { - return makeCloudFunction({ - handler, - provider, - service, - eventType, - triggerResource: this.triggerResource, - options: this.options, - }); - } -} - -/** 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; - }; -} diff --git a/src/v1/providers/tasks.ts b/src/v1/providers/tasks.ts deleted file mode 100644 index c9bf70849..000000000 --- a/src/v1/providers/tasks.ts +++ /dev/null @@ -1,175 +0,0 @@ -// 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. - -import * as express from "express"; - -import { convertIfPresent, convertInvoker, copyIfPresent } from "../../common/encoding"; -import { Request } from "../../common/providers/https"; -import { - onDispatchHandler, - RateLimits, - RetryConfig, - TaskContext, -} from "../../common/providers/tasks"; -import { - initV1Endpoint, - initTaskQueueTrigger, - ManifestEndpoint, - ManifestRequiredAPI, -} from "../../runtime/manifest"; -import { optionsToEndpoint, optionsToTrigger } from "../cloud-functions"; -import { DeploymentOptions } from "../function-configuration"; - -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; - - /** @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; -} - -/** - * Builder for creating a `TaskQueueFunction`. - */ -export class TaskQueueBuilder { - /** @internal */ - constructor( - private readonly tqOpts?: TaskQueueOptions, - private readonly depOpts?: DeploymentOptions - ) {} - - /** - * 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 - ): TaskQueueFunction { - // 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: any, context: TaskContext) => handler(data, context); - const func: any = onDispatchHandler(fixedLen); - - func.__trigger = { - ...optionsToTrigger(this.depOpts || {}), - taskQueueTrigger: {}, - }; - copyIfPresent(func.__trigger.taskQueueTrigger, this.tqOpts, "retryConfig"); - copyIfPresent(func.__trigger.taskQueueTrigger, this.tqOpts, "rateLimits"); - convertIfPresent( - func.__trigger.taskQueueTrigger, - this.tqOpts, - "invoker", - "invoker", - convertInvoker - ); - - func.__endpoint = { - platform: "gcfv1", - ...initV1Endpoint(this.depOpts), - ...optionsToEndpoint(this.depOpts), - taskQueueTrigger: initTaskQueueTrigger(this.depOpts), - }; - copyIfPresent( - func.__endpoint.taskQueueTrigger.retryConfig, - this.tqOpts?.retryConfig || {}, - "maxAttempts", - "maxBackoffSeconds", - "maxDoublings", - "maxRetrySeconds", - "minBackoffSeconds" - ); - copyIfPresent( - func.__endpoint.taskQueueTrigger.rateLimits, - this.tqOpts?.rateLimits || {}, - "maxConcurrentDispatches", - "maxDispatchesPerSecond" - ); - convertIfPresent( - func.__endpoint.taskQueueTrigger, - this.tqOpts, - "invoker", - "invoker", - convertInvoker - ); - - func.__requiredAPIs = [ - { - api: "cloudtasks.googleapis.com", - reason: "Needed for task queue functions", - }, - ]; - - func.run = handler; - - return func; - } -} - -/** - * 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 function taskQueue(options?: TaskQueueOptions): TaskQueueBuilder { - return new TaskQueueBuilder(options); -} diff --git a/src/v1/providers/testLab.ts b/src/v1/providers/testLab.ts deleted file mode 100644 index ae9f9e584..000000000 --- a/src/v1/providers/testLab.ts +++ /dev/null @@ -1,316 +0,0 @@ -// 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. - -import { CloudFunction, Event, EventContext, makeCloudFunction } from "../cloud-functions"; -import { DeploymentOptions } from "../function-configuration"; - -/** @internal */ -export const PROVIDER = "google.testing"; -/** @internal */ -export const SERVICE = "testing.googleapis.com"; -/** @internal */ -export const TEST_MATRIX_COMPLETE_EVENT_TYPE = "testMatrix.complete"; - -/** Handle events related to Test Lab test matrices. */ -export function testMatrix() { - return _testMatrixWithOpts({}); -} - -/** @internal */ -export function _testMatrixWithOpts(opts: DeploymentOptions) { - 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); -} - -/** Builder used to create Cloud Functions for Test Lab test matrices events. */ -export class TestMatrixBuilder { - /** @internal */ - constructor(private triggerResource: () => string, private options: DeploymentOptions) {} - - /** Handle a TestMatrix that reached a final test state. */ - onComplete( - handler: (testMatrix: TestMatrix, context: EventContext) => PromiseLike | any - ): CloudFunction { - const dataConstructor = (raw: Event) => { - return new TestMatrix(raw.data); - }; - return makeCloudFunction({ - provider: PROVIDER, - eventType: TEST_MATRIX_COMPLETE_EVENT_TYPE, - triggerResource: this.triggerResource, - service: SERVICE, - dataConstructor, - handler, - options: this.options, - }); - } -} - -/** TestMatrix captures details about a test run. */ -export 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; - - /** @internal */ - constructor(data: any) { - 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); - } -} - -/** Information about the client which invoked the test. */ -export class ClientInfo { - /** Client name, e.g. 'gcloud'. */ - name: string; - - /** Map of detailed information about the client which invoked the test. */ - details: { [key: string]: string }; - - /** @internal */ - constructor(data?: { name: string; clientInfoDetails?: Array<{ key: string; value?: string }> }) { - this.name = data?.name || ""; - this.details = {}; - for (const detail of data?.clientInfoDetails || []) { - this.details[detail.key] = detail.value || ""; - } - } -} - -/** Locations where the test results are stored. */ -export 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; - - /** @internal */ - constructor(data?: any) { - this.gcsPath = data?.googleCloudStorage?.gcsPath; - this.toolResultsHistoryId = data?.toolResultsHistory?.historyId; - this.toolResultsExecutionId = data?.toolResultsExecution?.executionId; - this.resultsUrl = data?.resultsUrl; - } -} - -/** - * 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"; diff --git a/src/v2/providers/identity.ts b/src/v2/providers/identity.ts index aa93edc2f..7de5fe94d 100644 --- a/src/v2/providers/identity.ts +++ b/src/v2/providers/identity.ts @@ -34,16 +34,31 @@ import { HttpsError, wrapHandler, } from "../../common/providers/identity"; -import { BlockingFunction } from "../../v1/cloud-functions"; import { wrapTraceContext } from "../trace"; import { Expression } from "../../params"; -import { initV2Endpoint } from "../../runtime/manifest"; +import { ManifestEndpoint, ManifestRequiredAPI, initV2Endpoint } from "../../runtime/manifest"; import * as options from "../options"; import { SecretParam } from "../../params/types"; import { withInit } from "../../common/onInit"; +import { Request, Response } from "express"; +import { TriggerAnnotation } from "../core"; export { AuthUserRecord, AuthBlockingEvent, HttpsError }; +export interface BlockingFunction { + /** @public */ + (req: Request, resp: Response): void | Promise; + + /** @alpha */ + __trigger: TriggerAnnotation; + + /** @alpha */ + __endpoint: ManifestEndpoint; + + /** @alpha */ + __requiredAPIs?: ManifestRequiredAPI[]; +} + /** @hidden Internally used when parsing the options. */ interface InternalOptions { opts: options.GlobalOptions; @@ -192,8 +207,8 @@ export function beforeUserCreated( optsOrHandler: | BlockingOptions | (( - event: AuthBlockingEvent - ) => BeforeCreateResponse | Promise | void | Promise), + event: AuthBlockingEvent + ) => BeforeCreateResponse | Promise | void | Promise), handler?: ( event: AuthBlockingEvent ) => BeforeCreateResponse | Promise | void | Promise @@ -232,8 +247,8 @@ export function beforeUserSignedIn( optsOrHandler: | BlockingOptions | (( - event: AuthBlockingEvent - ) => BeforeSignInResponse | Promise | void | Promise), + event: AuthBlockingEvent + ) => BeforeSignInResponse | Promise | void | Promise), handler?: ( event: AuthBlockingEvent ) => BeforeSignInResponse | Promise | void | Promise @@ -247,14 +262,14 @@ export function beforeOperation( optsOrHandler: | BlockingOptions | (( - event: AuthBlockingEvent - ) => - | BeforeCreateResponse - | BeforeSignInResponse - | void - | Promise - | Promise - | Promise), + event: AuthBlockingEvent + ) => + | BeforeCreateResponse + | BeforeSignInResponse + | void + | Promise + | Promise + | Promise), handler: ( event: AuthBlockingEvent ) => diff --git a/tsconfig.release.json b/tsconfig.release.json index 5d48aa842..1636f28fc 100644 --- a/tsconfig.release.json +++ b/tsconfig.release.json @@ -1,21 +1,24 @@ { "compilerOptions": { "declaration": true, - "lib": ["es2019"], + "lib": [ + "es2019" + ], "module": "commonjs", "noImplicitAny": false, "noUnusedLocals": true, "outDir": "lib", "stripInternal": true, "target": "es2019", - "typeRoots": ["./node_modules/@types"] + "typeRoots": [ + "./node_modules/@types" + ] }, "files": [ "./src/types/global.d.ts", - "./src/v1/index.ts", "./src/logger/index.ts", "./src/logger/compat.ts", "./src/v2/index.ts", "./src/bin/firebase-functions.ts" ] -} +} \ No newline at end of file diff --git a/v1/analytics.js b/v1/analytics.js deleted file mode 100644 index 7d725acc3..000000000 --- a/v1/analytics.js +++ /dev/null @@ -1,26 +0,0 @@ -// The MIT License (MIT) -// -// Copyright (c) 2021 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. - -// This file is not part of the firebase-functions SDK. It is used to silence the -// imports eslint plugin until it can understand import paths defined by node -// package exports. -// For more information, see github.com/import-js/eslint-plugin-import/issues/1810 diff --git a/v1/auth.js b/v1/auth.js deleted file mode 100644 index 7d725acc3..000000000 --- a/v1/auth.js +++ /dev/null @@ -1,26 +0,0 @@ -// The MIT License (MIT) -// -// Copyright (c) 2021 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. - -// This file is not part of the firebase-functions SDK. It is used to silence the -// imports eslint plugin until it can understand import paths defined by node -// package exports. -// For more information, see github.com/import-js/eslint-plugin-import/issues/1810 diff --git a/v1/database.js b/v1/database.js deleted file mode 100644 index 7d725acc3..000000000 --- a/v1/database.js +++ /dev/null @@ -1,26 +0,0 @@ -// The MIT License (MIT) -// -// Copyright (c) 2021 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. - -// This file is not part of the firebase-functions SDK. It is used to silence the -// imports eslint plugin until it can understand import paths defined by node -// package exports. -// For more information, see github.com/import-js/eslint-plugin-import/issues/1810 diff --git a/v1/firestore.js b/v1/firestore.js deleted file mode 100644 index 7d725acc3..000000000 --- a/v1/firestore.js +++ /dev/null @@ -1,26 +0,0 @@ -// The MIT License (MIT) -// -// Copyright (c) 2021 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. - -// This file is not part of the firebase-functions SDK. It is used to silence the -// imports eslint plugin until it can understand import paths defined by node -// package exports. -// For more information, see github.com/import-js/eslint-plugin-import/issues/1810 diff --git a/v1/index.js b/v1/index.js deleted file mode 100644 index 7d725acc3..000000000 --- a/v1/index.js +++ /dev/null @@ -1,26 +0,0 @@ -// The MIT License (MIT) -// -// Copyright (c) 2021 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. - -// This file is not part of the firebase-functions SDK. It is used to silence the -// imports eslint plugin until it can understand import paths defined by node -// package exports. -// For more information, see github.com/import-js/eslint-plugin-import/issues/1810 diff --git a/v1/pubsub.js b/v1/pubsub.js deleted file mode 100644 index 7d725acc3..000000000 --- a/v1/pubsub.js +++ /dev/null @@ -1,26 +0,0 @@ -// The MIT License (MIT) -// -// Copyright (c) 2021 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. - -// This file is not part of the firebase-functions SDK. It is used to silence the -// imports eslint plugin until it can understand import paths defined by node -// package exports. -// For more information, see github.com/import-js/eslint-plugin-import/issues/1810 diff --git a/v1/remoteConfig.js b/v1/remoteConfig.js deleted file mode 100644 index 7d725acc3..000000000 --- a/v1/remoteConfig.js +++ /dev/null @@ -1,26 +0,0 @@ -// The MIT License (MIT) -// -// Copyright (c) 2021 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. - -// This file is not part of the firebase-functions SDK. It is used to silence the -// imports eslint plugin until it can understand import paths defined by node -// package exports. -// For more information, see github.com/import-js/eslint-plugin-import/issues/1810 diff --git a/v1/storage.js b/v1/storage.js deleted file mode 100644 index 7d725acc3..000000000 --- a/v1/storage.js +++ /dev/null @@ -1,26 +0,0 @@ -// The MIT License (MIT) -// -// Copyright (c) 2021 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. - -// This file is not part of the firebase-functions SDK. It is used to silence the -// imports eslint plugin until it can understand import paths defined by node -// package exports. -// For more information, see github.com/import-js/eslint-plugin-import/issues/1810 diff --git a/v1/tasks.js b/v1/tasks.js deleted file mode 100644 index ae33ba821..000000000 --- a/v1/tasks.js +++ /dev/null @@ -1,26 +0,0 @@ -// 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. - -// This file is not part of the firebase-functions SDK. It is used to silence the -// imports eslint plugin until it can understand import paths defined by node -// package exports. -// For more information, see github.com/import-js/eslint-plugin-import/issues/1810 diff --git a/v1/testLab.js b/v1/testLab.js deleted file mode 100644 index 7d725acc3..000000000 --- a/v1/testLab.js +++ /dev/null @@ -1,26 +0,0 @@ -// The MIT License (MIT) -// -// Copyright (c) 2021 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. - -// This file is not part of the firebase-functions SDK. It is used to silence the -// imports eslint plugin until it can understand import paths defined by node -// package exports. -// For more information, see github.com/import-js/eslint-plugin-import/issues/1810