Skip to content

Commit f852d27

Browse files
taeoldlisajian
andauthored
Firebase Functions 7.0.0 (#1758)
* BREAKING: Upgrade TypeScript to v5.9.3 (#1746) Upgrades from TypeScript v4.3.5 to v5.9.3. All tests pass successfully. * BREAKING: Drop Node.js 14/16 support, require Node.js >=18 (#1747) * BREAKING: Drop Node.js 14/16 support, require Node.js >=18 - Update package.json engines to require Node.js >=18.0.0 - Upgrade @types/node from v14 to v18 - Update TypeScript target from ES2019 to ES2022 - Add useDefineForClassFields: false for backward compatibility - Update CI/CD workflows to test Node.js 18, 20, 22, and 24 - Set default CI/CD Node.js version to 24 - Update integration test documentation * BREAKING: remove functions.config() implementation (#1748) Replace functions.config() implementation with an error that provides clear migration guidance to the params module. This removes the deprecated API as planned for the next major release while helping developers migrate. The error message directs users to: https://firebase.google.com/docs/functions/config-env#migrate-config * chore: migrate to ESLint v9 and Flat Config (#1753) Upgraded eslint to v9 and replaced the legacy .eslintrc.js with the new eslint.config.js format. Applied minor fixes to 4 files (renaming unused catch variables to _e and one small refactor) to satisfy slightly stricter baseline rules from updated plugins. Mostly doing this due to our upgrade in TS to latest v5 version which the old versions of eslint ts plugins no longer support. * chore: enable esModuleInterop (#1751) * feat: add async error handling to onRequest (#1755) BREAKING CHANGE: Unhandled errors in async onRequest handlers now immediately return a 500 Internal Server Error instead of hanging until timeout. This may affect clients relying on 504 Gateway Timeout for retry logic. * BREAKING: Break TS build that uses functions.config() (#1757) Type out `functions.config()` API. Use of `functions.config()` API should now cause a BUILD error at compile time. ```ts import * as functions from "firebase-functions"; import {onRequest} from "firebase-functions/https"; import * as logger from "firebase-functions/logger"; const cfg = functions.config() export const helloWorld = onRequest((request, response) => { logger.info("Hello logs!", cfg); response.send("Hello from Firebase!"); }); ``` ```bash $ npm run build > build > tsc src/index.ts:5:23 - error TS2349: This expression is not callable. Type 'never' has no call signatures. 5 const cfg = functions.config() ~~~~~~ Found 1 error in src/index.ts:5 ``` * Add Firebase Data Connect v2 support (#1727) * Add Firebase Data Connect v2 support * Export dataconnect * Fix export * Rename Extract to VarName, since Extract is a built in type * Include auth context in event payload * Stronger typing for data connect params * Fix formatting and address comments * Apply another suggestion * Add region and fix bug in which event.service, event.connector, event.operation gets populated * Remove locations/... segment * Address comments * Fix linter * feat: enable ESM support via dual-publishing (#1750) - Configure tsdown to build both CJS and ESM outputs. - Update package.json exports to support both 'require' and 'import'. - Fix type hygiene issues by using explicit 'export type'. - Update protos/update.sh to generate ESM version of compiledFirestore and fix its imports for Node.js compatibility. - Configure build aliases to handle relative paths to protos correctly in both CJS and ESM builds. - Add packaging integration test to CI. ~Note: I enabled `esModuleInterop` in tsconfig.release.json to support default imports from CommonJS modules (like cors), which is required for proper ESM interop. This caused some chain-effect that required updating several unit tests and source files to use default imports for other CJS dependencies (e.g., fs, nock, jsonwebtoken) to align with the new compiler configuration.~ Fixed in #1751. * lock down permission per GitHub alert. * update lint rule to enforce prettier rules. * chore: update CHANGELOG for v7.0.0 * format. --------- Co-authored-by: Lisa Jian <[email protected]>
1 parent 1bd75b0 commit f852d27

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+6923
-1095
lines changed

.eslintignore

Lines changed: 0 additions & 12 deletions
This file was deleted.

.eslintrc.js

Lines changed: 0 additions & 70 deletions
This file was deleted.

.github/workflows/docs.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
- uses: actions/checkout@v4
1313
- uses: actions/setup-node@v4
1414
with:
15-
node-version: "20"
15+
node-version: "24"
1616
- name: Cache npm
1717
uses: actions/cache@v4
1818
with:

.github/workflows/postmerge.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
- uses: actions/checkout@v3
3131
- uses: actions/setup-node@v3
3232
with:
33-
node-version: 18
33+
node-version: 24
3434

3535
- uses: google-github-actions/auth@v0
3636
with:

.github/workflows/test.yaml

Lines changed: 64 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ on:
44
- pull_request
55
- push
66

7+
permissions:
8+
contents: read
9+
710
env:
811
CI: true
912

@@ -14,17 +17,36 @@ jobs:
1417
strategy:
1518
matrix:
1619
node-version:
17-
- 18.x
20+
- 20.x
1821
steps:
19-
- uses: actions/checkout@v3
20-
with:
21-
fetch-depth: 0
22-
- uses: actions/setup-node@v3
22+
- uses: actions/checkout@v4
23+
- uses: actions/setup-node@v4
2324
with:
2425
node-version: ${{ matrix.node-version }}
2526
cache: npm
2627
- run: npm ci
2728
- run: npm run lint
29+
30+
build:
31+
runs-on: ubuntu-latest
32+
steps:
33+
- uses: actions/checkout@v4
34+
- uses: actions/setup-node@v4
35+
with:
36+
node-version: 20.x
37+
cache: npm
38+
- run: npm ci
39+
- run: npm run build
40+
- run: npm pack
41+
- uses: actions/upload-artifact@v4
42+
with:
43+
name: lib
44+
path: lib/
45+
- uses: actions/upload-artifact@v4
46+
with:
47+
name: tarball
48+
path: firebase-functions-*.tgz
49+
2850
unit:
2951
runs-on: ubuntu-latest
3052
strategy:
@@ -33,36 +55,58 @@ jobs:
3355
- 18.x
3456
- 20.x
3557
- 22.x
58+
- 24.x
3659
steps:
37-
- uses: actions/checkout@v1
38-
- uses: actions/setup-node@v1
60+
- uses: actions/checkout@v4
61+
- uses: actions/setup-node@v4
3962
with:
4063
node-version: ${{ matrix.node-version }}
41-
- name: Cache npm
42-
uses: actions/cache@v4
43-
with:
44-
path: ~/.npm
45-
key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }}
64+
cache: npm
4665
- run: npm ci
4766
- run: npm run test
67+
4868
integration:
49-
needs: "unit"
69+
needs: build
5070
runs-on: ubuntu-latest
5171
strategy:
5272
matrix:
5373
node-version:
5474
- 18.x
5575
- 20.x
5676
- 22.x
77+
- 24.x
5778
steps:
58-
- uses: actions/checkout@v1
59-
- uses: actions/setup-node@v1
79+
- uses: actions/checkout@v4
80+
- uses: actions/setup-node@v4
6081
with:
6182
node-version: ${{ matrix.node-version }}
62-
- name: Cache npm
63-
uses: actions/cache@v4
64-
with:
65-
path: ~/.npm
66-
key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }}
83+
cache: npm
6784
- run: npm ci
85+
- uses: actions/download-artifact@v4
86+
with:
87+
name: lib
88+
path: lib
6889
- run: npm run test:bin
90+
env:
91+
SKIP_BUILD: true
92+
93+
packaging:
94+
needs: build
95+
runs-on: ubuntu-latest
96+
strategy:
97+
matrix:
98+
node-version:
99+
- 18.x
100+
- 20.x
101+
- 22.x
102+
- 24.x
103+
steps:
104+
- uses: actions/checkout@v4
105+
- uses: actions/setup-node@v4
106+
with:
107+
node-version: ${{ matrix.node-version }}
108+
- uses: actions/download-artifact@v4
109+
with:
110+
name: tarball
111+
path: .
112+
- run: chmod +x ./scripts/test-packaging.sh && ./scripts/test-packaging.sh firebase-functions-*.tgz

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
- BREAKING: Drop support for Node.js 16. Minimum supported version is now Node.js 18. (#1747)
2+
- BREAKING: Remove deprecated `functions.config()` API. Use `params` module for environment variables instead. (#1748)
3+
- BREAKING: Upgrade to TypeScript v5 and target ES2022. (#1746)
4+
- BREAKING: Unhandled errors in async `onRequest` handlers in the Emulator now return a 500 error immediately. (#1755)
5+
- Add support for ESM (ECMAScript Modules) alongside CommonJS. (#1750)
6+
- Add `onMutationExecuted()` trigger for Firebase Data Connect. (#1727)

eslint.config.js

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
const { FlatCompat } = require("@eslint/eslintrc");
2+
const js = require("@eslint/js");
3+
const path = require("path");
4+
5+
const compat = new FlatCompat({
6+
baseDirectory: __dirname,
7+
recommendedConfig: js.configs.recommended,
8+
allConfig: js.configs.all
9+
});
10+
11+
module.exports = [
12+
{
13+
ignores: [
14+
"lib/",
15+
"dev/",
16+
"node_modules/",
17+
"coverage/",
18+
"docgen/",
19+
"v1/",
20+
"v2/",
21+
"logger/",
22+
"dist/",
23+
"spec/fixtures/",
24+
"scripts/**/*.js",
25+
"scripts/**/*.mjs",
26+
"protos/",
27+
".prettierrc.js",
28+
"eslint.config.*",
29+
"tsdown.config.*",
30+
"scripts/bin-test/sources/esm-ext/index.mjs",
31+
],
32+
},
33+
...compat.extends(
34+
"eslint:recommended",
35+
"plugin:@typescript-eslint/recommended",
36+
"plugin:@typescript-eslint/recommended-requiring-type-checking",
37+
"plugin:jsdoc/recommended",
38+
"google",
39+
"prettier"
40+
),
41+
{
42+
languageOptions: {
43+
parser: require("@typescript-eslint/parser"),
44+
parserOptions: {
45+
project: "tsconfig.json",
46+
tsconfigRootDir: __dirname,
47+
},
48+
ecmaVersion: 2022
49+
},
50+
plugins: {
51+
"prettier": require("eslint-plugin-prettier"),
52+
},
53+
rules: {
54+
"jsdoc/newline-after-description": "off",
55+
"jsdoc/require-jsdoc": ["warn", { publicOnly: true }],
56+
"jsdoc/check-tag-names": ["warn", { definedTags: ["alpha", "remarks", "typeParam", "packageDocumentation", "hidden"] }],
57+
"no-restricted-globals": ["error", "name", "length"],
58+
"prefer-arrow-callback": "error",
59+
"prettier/prettier": "error",
60+
"require-atomic-updates": "off", // This rule is so noisy and isn't useful: https://github.com/eslint/eslint/issues/11899
61+
"require-jsdoc": "off", // This rule is deprecated and superseded by jsdoc/require-jsdoc.
62+
"valid-jsdoc": "off", // This is deprecated but included in recommended configs.
63+
"no-prototype-builtins": "warn",
64+
"no-useless-escape": "warn",
65+
"prefer-promise-reject-errors": "warn",
66+
},
67+
},
68+
{
69+
files: ["**/*.ts"],
70+
rules: {
71+
"jsdoc/require-param-type": "off",
72+
"jsdoc/require-returns-type": "off",
73+
// Google style guide allows us to omit trivial parameters and returns
74+
"jsdoc/require-param": "off",
75+
"jsdoc/require-returns": "off",
76+
77+
"@typescript-eslint/no-invalid-this": "error",
78+
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_", caughtErrorsIgnorePattern: "^_" }], // Unused vars should not exist.
79+
"@typescript-eslint/no-misused-promises": "warn", // rule does not work with async handlers for express.
80+
"no-invalid-this": "off", // Turned off in favor of @typescript-eslint/no-invalid-this.
81+
"no-unused-vars": "off", // Off in favor of @typescript-eslint/no-unused-vars.
82+
eqeqeq: ["error", "always", { null: "ignore" }],
83+
camelcase: ["error", { properties: "never" }], // snake_case allowed in properties iif to satisfy an external contract / style
84+
85+
// Ideally, all these warning should be error - let's fix them in the future.
86+
"@typescript-eslint/no-unsafe-argument": "warn",
87+
"@typescript-eslint/no-unsafe-assignment": "warn",
88+
"@typescript-eslint/no-unsafe-call": "warn",
89+
"@typescript-eslint/no-unsafe-member-access": "warn",
90+
"@typescript-eslint/no-unsafe-return": "warn",
91+
"@typescript-eslint/restrict-template-expressions": "warn",
92+
"@typescript-eslint/no-explicit-any": "warn",
93+
"@typescript-eslint/no-redundant-type-constituents": "warn",
94+
"@typescript-eslint/no-base-to-string": "warn",
95+
"@typescript-eslint/no-duplicate-type-constituents": "warn",
96+
"@typescript-eslint/no-require-imports": "warn",
97+
"@typescript-eslint/no-empty-object-type": "warn",
98+
"@typescript-eslint/prefer-promise-reject-errors": "warn",
99+
},
100+
},
101+
{
102+
files: ["**/*.spec.ts", "**/*.spec.js", "spec/helper.ts", "scripts/bin-test/**/*.ts", "integration_test/**/*.ts"],
103+
languageOptions: {
104+
globals: {
105+
mocha: true,
106+
},
107+
},
108+
rules: {
109+
"@typescript-eslint/no-unused-expressions": "off",
110+
}
111+
},
112+
];

integration_test/functions/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { GoogleAuth } from "google-auth-library";
33
import { Request, Response } from "express";
44
import * as admin from "firebase-admin";
55
import * as functions from "firebase-functions";
6-
import * as fs from "fs";
6+
import fs from "fs";
77
import fetch from "node-fetch";
88

99
import * as v1 from "./v1";

integration_test/functions/src/v1/pubsub-tests.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ export const pubsubTests: any = functions
1313
let testId: string;
1414
try {
1515
testId = m.json.testId;
16-
} catch (e) {
17-
/* Ignored. Covered in another test case that `event.data.json` works. */
16+
} catch (_e) {
17+
// Ignored. Covered in another test case that `event.data.json` works.
1818
}
1919

2020
return new TestSuite<PubsubMessage>("pubsub onPublish")

mocha/setup.ts

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,6 @@
1-
import * as chai from "chai";
2-
import * as chaiAsPromisedModule from "chai-as-promised";
3-
import * as nockModule from "nock";
4-
5-
// Normalize CommonJS exports so ts-node (Node.js 20) and Node.js 22's strip-only loader
6-
// both receive callable modules without relying on esModuleInterop.
7-
type ChaiPlugin = Parameters<typeof chai.use>[0];
8-
type NockModule = typeof nockModule;
9-
10-
const chaiAsPromisedExport = chaiAsPromisedModule as ChaiPlugin & { default?: ChaiPlugin };
11-
const chaiAsPromised = chaiAsPromisedExport.default ?? chaiAsPromisedExport;
12-
const nockExport = nockModule as NockModule & { default?: NockModule };
13-
const nock = nockExport.default ?? nockExport;
1+
import chai from "chai";
2+
import chaiAsPromised from "chai-as-promised";
3+
import nock from "nock";
144

155
chai.use(chaiAsPromised);
16-
176
nock.disableNetConnect();

0 commit comments

Comments
 (0)