Skip to content

Commit bbb905b

Browse files
authored
Merge branch 'master' into fix-params-type-exports
2 parents a67a19a + fd0e291 commit bbb905b

18 files changed

+109
-31
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
- Export param types (SecretParam, StringParam, etc.) from firebase-functions/params for type annotations. (#1789)
22
- Remove attemptDeadlineSeconds in v2 scheduled functions. (#1776)
3+
- Allow `JsonSecretParam` in function `secrets` option arrays. (#1788)

spec/v1/cloud-functions.spec.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
RESET_VALUE,
3232
} from "../../src/v1";
3333
import { MINIMAL_V1_ENDPOINT } from "../fixtures";
34+
import { defineJsonSecret, defineSecret } from "../../src/params";
3435

3536
describe("makeCloudFunction", () => {
3637
const cloudFunctionArgs: MakeCloudFunctionArgs<any> = {
@@ -161,6 +162,31 @@ describe("makeCloudFunction", () => {
161162
});
162163
});
163164

165+
it("should accept all valid secret types in secrets array (type test)", () => {
166+
// This is a compile-time type test. If any of these types are not assignable
167+
// to the secrets array, TypeScript will fail to compile this test file.
168+
const jsonSecret = defineJsonSecret<{ key: string }>("JSON_SECRET");
169+
const stringSecret = defineSecret("STRING_SECRET");
170+
const plainSecret = "PLAIN_SECRET";
171+
172+
const cf = makeCloudFunction({
173+
provider: "mock.provider",
174+
eventType: "mock.event",
175+
service: "service",
176+
triggerResource: () => "resource",
177+
handler: () => null,
178+
options: {
179+
secrets: [plainSecret, stringSecret, jsonSecret],
180+
},
181+
});
182+
183+
expect(cf.__endpoint.secretEnvironmentVariables).to.deep.equal([
184+
{ key: "PLAIN_SECRET" },
185+
{ key: "STRING_SECRET" },
186+
{ key: "JSON_SECRET" },
187+
]);
188+
});
189+
164190
it("should set retry given failure policy in __endpoint", () => {
165191
const cf = makeCloudFunction({
166192
provider: "mock.provider",

spec/v2/options.spec.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// The MIT License (MIT)
2+
//
3+
// Copyright (c) 2025 Firebase
4+
//
5+
// Permission is hereby granted, free of charge, to any person obtaining a copy
6+
// of this software and associated documentation files (the "Software"), to deal
7+
// in the Software without restriction, including without limitation the rights
8+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
// copies of the Software, and to permit persons to whom the Software is
10+
// furnished to do so, subject to the following conditions:
11+
//
12+
// The above copyright notice and this permission notice shall be included in all
13+
// copies or substantial portions of the Software.
14+
//
15+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
// SOFTWARE.
22+
23+
import { expect } from "chai";
24+
import { defineJsonSecret, defineSecret } from "../../src/params";
25+
import { GlobalOptions } from "../../src/v2/options";
26+
27+
describe("GlobalOptions", () => {
28+
it("should accept all valid secret types in secrets array (type test)", () => {
29+
// This is a compile-time type test. If any of these types are not assignable
30+
// to the secrets array, TypeScript will fail to compile this test file.
31+
const jsonSecret = defineJsonSecret<{ key: string }>("JSON_SECRET");
32+
const stringSecret = defineSecret("STRING_SECRET");
33+
const plainSecret = "PLAIN_SECRET";
34+
35+
const opts: GlobalOptions = {
36+
secrets: [plainSecret, stringSecret, jsonSecret],
37+
};
38+
39+
expect(opts.secrets).to.have.length(3);
40+
});
41+
});

src/params/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,12 @@ export class JsonSecretParam<T = any> {
535535
}
536536
}
537537

538+
/**
539+
* A union type representing all valid secret parameter types that can be used
540+
* in a function's `secrets` configuration array.
541+
*/
542+
export type SupportedSecretParam = string | SecretParam | JsonSecretParam<unknown>;
543+
538544
/**
539545
* A parametrized value of String type that will be read from .env files
540546
* if present, or prompted for by the CLI if missing.

src/v1/cloud-functions.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import {
4343
ManifestRequiredAPI,
4444
} from "../runtime/manifest";
4545
import { ResetValue } from "../common/options";
46-
import { SecretParam } from "../params/types";
46+
import { SupportedSecretParam } from "../params/types";
4747
import { withInit } from "../common/onInit";
4848

4949
export { Change } from "../common/change";
@@ -638,8 +638,10 @@ export function optionsToEndpoint(options: DeploymentOptions): ManifestEndpoint
638638
options,
639639
"secretEnvironmentVariables",
640640
"secrets",
641-
(secrets: (string | SecretParam)[]) =>
642-
secrets.map((secret) => ({ key: secret instanceof SecretParam ? secret.name : secret }))
641+
(secrets: SupportedSecretParam[]) =>
642+
secrets.map((secret) => ({
643+
key: typeof secret === "string" ? secret : secret.name,
644+
}))
643645
);
644646
if (options?.vpcConnector !== undefined) {
645647
if (options.vpcConnector === null || options.vpcConnector instanceof ResetValue) {

src/v1/function-builder.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import * as express from "express";
2424

2525
import { ResetValue } from "../common/options";
26-
import { Expression, SecretParam } from "../params/types";
26+
import { Expression } from "../params/types";
2727
import { EventContext } from "./cloud-functions";
2828
import {
2929
DeploymentOptions,
@@ -200,7 +200,7 @@ function assertRuntimeOptionsValid(runtimeOptions: RuntimeOptions): boolean {
200200

201201
if (runtimeOptions.secrets !== undefined) {
202202
const invalidSecrets = runtimeOptions.secrets.filter(
203-
(s) => !/^[A-Za-z\d\-_]+$/.test(s instanceof SecretParam ? s.name : s)
203+
(s) => !/^[A-Za-z\d\-_]+$/.test(typeof s === "string" ? s : s.name)
204204
);
205205
if (invalidSecrets.length > 0) {
206206
throw new Error(

src/v1/function-configuration.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Expression } from "../params";
22
import { ResetValue } from "../common/options";
3-
import { SecretParam } from "../params/types";
3+
import { SupportedSecretParam } from "../params/types";
44

55
export { RESET_VALUE } from "../common/options";
66

@@ -235,7 +235,7 @@ export interface RuntimeOptions {
235235
/*
236236
* Secrets to bind to a function instance.
237237
*/
238-
secrets?: (string | SecretParam)[];
238+
secrets?: SupportedSecretParam[];
239239

240240
/**
241241
* Determines whether Firebase AppCheck is enforced.

src/v2/options.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import { RESET_VALUE, ResetValue } from "../common/options";
3535
import { ManifestEndpoint } from "../runtime/manifest";
3636
import { TriggerAnnotation } from "./core";
3737
import { declaredParams, Expression } from "../params";
38-
import { ParamSpec, SecretParam } from "../params/types";
38+
import { ParamSpec, SupportedSecretParam } from "../params/types";
3939
import { HttpsOptions } from "./providers/https";
4040
import * as logger from "../logger";
4141

@@ -210,7 +210,7 @@ export interface GlobalOptions {
210210
/*
211211
* Secrets to bind to a function.
212212
*/
213-
secrets?: (string | SecretParam)[];
213+
secrets?: SupportedSecretParam[];
214214

215215
/**
216216
* Determines whether Firebase App Check is enforced. Defaults to false.
@@ -396,8 +396,10 @@ export function optionsToEndpoint(
396396
opts,
397397
"secretEnvironmentVariables",
398398
"secrets",
399-
(secrets: (string | SecretParam)[]) =>
400-
secrets.map((secret) => ({ key: secret instanceof SecretParam ? secret.name : secret }))
399+
(secrets: SupportedSecretParam[]) =>
400+
secrets.map((secret) => ({
401+
key: typeof secret === "string" ? secret : secret.name,
402+
}))
401403
);
402404

403405
return endpoint;

src/v2/providers/alerts/alerts.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { CloudEvent, CloudFunction } from "../../core";
2626
import { Expression } from "../../../params";
2727
import { wrapTraceContext } from "../../trace";
2828
import * as options from "../../options";
29-
import { SecretParam } from "../../../params/types";
29+
import { SupportedSecretParam } from "../../../params/types";
3030
import { withInit } from "../../../common/onInit";
3131

3232
/**
@@ -180,7 +180,7 @@ export interface FirebaseAlertOptions extends options.EventHandlerOptions {
180180
/*
181181
* Secrets to bind to a function.
182182
*/
183-
secrets?: (string | SecretParam)[];
183+
secrets?: SupportedSecretParam[];
184184

185185
/** Whether failed executions should be delivered again. */
186186
retry?: boolean | Expression<boolean> | ResetValue;

src/v2/providers/alerts/appDistribution.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { CloudEvent, CloudFunction } from "../../core";
3131
import { wrapTraceContext } from "../../trace";
3232
import { convertAlertAndApp, FirebaseAlertData, getEndpointAnnotation } from "./alerts";
3333
import * as options from "../../options";
34-
import { SecretParam } from "../../../params/types";
34+
import { SupportedSecretParam } from "../../../params/types";
3535
import { withInit } from "../../../common/onInit";
3636

3737
/**
@@ -191,7 +191,7 @@ export interface AppDistributionOptions extends options.EventHandlerOptions {
191191
/*
192192
* Secrets to bind to a function.
193193
*/
194-
secrets?: (string | SecretParam)[];
194+
secrets?: SupportedSecretParam[];
195195

196196
/** Whether failed executions should be delivered again. */
197197
retry?: boolean | Expression<boolean> | ResetValue;

0 commit comments

Comments
 (0)