Skip to content

Commit 7cba2ab

Browse files
committed
Update functions template to meet modern dev practices.
1 parent 33c310e commit 7cba2ab

File tree

15 files changed

+136
-293
lines changed

15 files changed

+136
-293
lines changed

src/init/features/functions.spec.ts

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,8 @@ describe("functions", () => {
7272
it("creates a new javascript codebase with the correct configuration", async () => {
7373
const setup = { config: { functions: [] }, rcfile: {} };
7474
prompt.select.onFirstCall().resolves("javascript");
75-
76-
// say "yes" to enabling eslint for the js project
77-
prompt.confirm.onFirstCall().resolves(true);
7875
// do not install dependencies
79-
prompt.confirm.onSecondCall().resolves(false);
76+
prompt.confirm.onFirstCall().resolves(false);
8077
askWriteProjectFileStub = sandbox.stub(emptyConfig, "askWriteProjectFile");
8178
askWriteProjectFileStub.resolves();
8279

@@ -86,11 +83,11 @@ describe("functions", () => {
8683
source: TEST_SOURCE_DEFAULT,
8784
codebase: TEST_CODEBASE_DEFAULT,
8885
ignore: ["node_modules", ".git", "firebase-debug.log", "firebase-debug.*.log", "*.local"],
89-
predeploy: ['npm --prefix "$RESOURCE_DIR" run lint'],
86+
predeploy: [],
9087
});
9188
expect(askWriteProjectFileStub.getCalls().map((call) => call.args[0])).to.deep.equal([
9289
`${TEST_SOURCE_DEFAULT}/package.json`,
93-
`${TEST_SOURCE_DEFAULT}/.eslintrc.js`,
90+
`${TEST_SOURCE_DEFAULT}/biome.json`,
9491
`${TEST_SOURCE_DEFAULT}/index.js`,
9592
`${TEST_SOURCE_DEFAULT}/.gitignore`,
9693
]);
@@ -99,10 +96,8 @@ describe("functions", () => {
9996
it("creates a new typescript codebase with the correct configuration", async () => {
10097
const setup = { config: { functions: [] }, rcfile: {} };
10198
prompt.select.onFirstCall().resolves("typescript");
102-
// Lint
103-
prompt.confirm.onFirstCall().resolves(true);
10499
// do not install dependencies
105-
prompt.confirm.onSecondCall().resolves(false);
100+
prompt.confirm.onFirstCall().resolves(false);
106101
askWriteProjectFileStub = sandbox.stub(emptyConfig, "askWriteProjectFile");
107102
askWriteProjectFileStub.resolves();
108103

@@ -112,15 +107,11 @@ describe("functions", () => {
112107
source: TEST_SOURCE_DEFAULT,
113108
codebase: TEST_CODEBASE_DEFAULT,
114109
ignore: ["node_modules", ".git", "firebase-debug.log", "firebase-debug.*.log", "*.local"],
115-
predeploy: [
116-
'npm --prefix "$RESOURCE_DIR" run lint',
117-
'npm --prefix "$RESOURCE_DIR" run build',
118-
],
110+
predeploy: ['npm --prefix "$RESOURCE_DIR" run build'],
119111
});
120112
expect(askWriteProjectFileStub.getCalls().map((call) => call.args[0])).to.deep.equal([
121113
`${TEST_SOURCE_DEFAULT}/package.json`,
122-
`${TEST_SOURCE_DEFAULT}/.eslintrc.js`,
123-
`${TEST_SOURCE_DEFAULT}/tsconfig.dev.json`,
114+
`${TEST_SOURCE_DEFAULT}/biome.json`,
124115
`${TEST_SOURCE_DEFAULT}/tsconfig.json`,
125116
`${TEST_SOURCE_DEFAULT}/src/index.ts`,
126117
`${TEST_SOURCE_DEFAULT}/.gitignore`,
@@ -138,9 +129,8 @@ describe("functions", () => {
138129

139130
// Initialize as JavaScript
140131
prompt.select.onSecondCall().resolves("javascript");
141-
// Lint but do not install dependencies
142-
prompt.confirm.onFirstCall().resolves(true);
143-
prompt.confirm.onSecondCall().resolves(false);
132+
// do not install dependencies
133+
prompt.confirm.onFirstCall().resolves(false);
144134
askWriteProjectFileStub = sandbox.stub(config, "askWriteProjectFile");
145135
askWriteProjectFileStub.resolves();
146136

@@ -157,7 +147,7 @@ describe("functions", () => {
157147
"firebase-debug.*.log",
158148
"*.local",
159149
],
160-
predeploy: ['npm --prefix "$RESOURCE_DIR" run lint'],
150+
predeploy: [],
161151
},
162152
{
163153
source: "testsource2",
@@ -169,12 +159,12 @@ describe("functions", () => {
169159
"firebase-debug.*.log",
170160
"*.local",
171161
],
172-
predeploy: ['npm --prefix "$RESOURCE_DIR" run lint'],
162+
predeploy: [],
173163
},
174164
]);
175165
expect(askWriteProjectFileStub.getCalls().map((call) => call.args[0])).to.deep.equal([
176166
`testsource2/package.json`,
177-
`testsource2/.eslintrc.js`,
167+
`testsource2/biome.json`,
178168
`testsource2/index.js`,
179169
`testsource2/.gitignore`,
180170
]);
@@ -185,9 +175,8 @@ describe("functions", () => {
185175
prompt.select.onFirstCall().resolves("reinit");
186176
prompt.select.onSecondCall().resolves("javascript");
187177

188-
// Lint but do not install dependencies
189-
prompt.confirm.onFirstCall().resolves(true);
190-
prompt.confirm.onSecondCall().resolves(false);
178+
// do not install dependencies
179+
prompt.confirm.onFirstCall().resolves(false);
191180
askWriteProjectFileStub = sandbox.stub(config, "askWriteProjectFile");
192181
askWriteProjectFileStub.resolves();
193182

@@ -204,12 +193,12 @@ describe("functions", () => {
204193
"firebase-debug.*.log",
205194
"*.local",
206195
],
207-
predeploy: ['npm --prefix "$RESOURCE_DIR" run lint'],
196+
predeploy: [],
208197
},
209198
]);
210199
expect(askWriteProjectFileStub.getCalls().map((call) => call.args[0])).to.deep.equal([
211200
`${TEST_SOURCE_DEFAULT}/package.json`,
212-
`${TEST_SOURCE_DEFAULT}/.eslintrc.js`,
201+
`${TEST_SOURCE_DEFAULT}/biome.json`,
213202
`${TEST_SOURCE_DEFAULT}/index.js`,
214203
`${TEST_SOURCE_DEFAULT}/.gitignore`,
215204
]);

src/init/features/functions/javascript.ts

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,23 @@
11
import { askInstallDependencies } from "./npm-dependencies";
2-
import { confirm } from "../../../prompt";
32
import { configForCodebase } from "../../../functions/projectConfig";
43
import { readTemplateSync } from "../../../templates";
54
import * as supported from "../../../deploy/functions/runtimes/supported";
65

76
const INDEX_TEMPLATE = readTemplateSync("init/functions/javascript/index.js");
8-
const PACKAGE_LINTING_TEMPLATE = readTemplateSync("init/functions/javascript/package.lint.json");
9-
const PACKAGE_NO_LINTING_TEMPLATE = readTemplateSync(
10-
"init/functions/javascript/package.nolint.json",
11-
);
12-
const ESLINT_TEMPLATE = readTemplateSync("init/functions/javascript/_eslintrc");
7+
const PACKAGE_TEMPLATE = readTemplateSync("init/functions/javascript/package.json");
8+
const BIOME_TEMPLATE = readTemplateSync("init/functions/javascript/biome.json");
139
const GITIGNORE_TEMPLATE = readTemplateSync("init/functions/javascript/_gitignore");
1410

1511
export async function setup(setup: any, config: any): Promise<any> {
16-
setup.functions.lint =
17-
setup.functions.lint ||
18-
(await confirm("Do you want to use ESLint to catch probable bugs and enforce style?"));
19-
if (setup.functions.lint) {
20-
const cbconfig = configForCodebase(setup.config.functions, setup.functions.codebase);
21-
cbconfig.predeploy = ['npm --prefix "$RESOURCE_DIR" run lint'];
22-
await config.askWriteProjectFile(
23-
`${setup.functions.source}/package.json`,
24-
PACKAGE_LINTING_TEMPLATE.replace(
25-
"{{RUNTIME}}",
26-
supported.latest("nodejs").replace("nodejs", ""),
27-
),
28-
);
29-
await config.askWriteProjectFile(`${setup.functions.source}/.eslintrc.js`, ESLINT_TEMPLATE);
30-
} else {
31-
await config.askWriteProjectFile(
32-
`${setup.functions.source}/package.json`,
33-
PACKAGE_NO_LINTING_TEMPLATE.replace(
34-
"{{RUNTIME}}",
35-
supported.latest("nodejs").replace("nodejs", ""),
36-
),
37-
);
38-
}
12+
const cbconfig = configForCodebase(setup.config.functions, setup.functions.codebase);
13+
cbconfig.predeploy = [];
3914

15+
const runtime = supported.latest("nodejs").replace("nodejs", "");
16+
await config.askWriteProjectFile(
17+
`${setup.functions.source}/package.json`,
18+
PACKAGE_TEMPLATE.replace("{{RUNTIME}}", runtime),
19+
);
20+
await config.askWriteProjectFile(`${setup.functions.source}/biome.json`, BIOME_TEMPLATE);
4021
await config.askWriteProjectFile(`${setup.functions.source}/index.js`, INDEX_TEMPLATE);
4122
await config.askWriteProjectFile(`${setup.functions.source}/.gitignore`, GITIGNORE_TEMPLATE);
4223
await askInstallDependencies(setup.functions, config);

src/init/features/functions/typescript.ts

Lines changed: 12 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,28 @@
11
import { askInstallDependencies } from "./npm-dependencies";
2-
import { confirm } from "../../../prompt";
32
import { configForCodebase } from "../../../functions/projectConfig";
43
import { readTemplateSync } from "../../../templates";
54
import * as supported from "../../../deploy/functions/runtimes/supported";
65

7-
const PACKAGE_LINTING_TEMPLATE = readTemplateSync("init/functions/typescript/package.lint.json");
8-
const PACKAGE_NO_LINTING_TEMPLATE = readTemplateSync(
9-
"init/functions/typescript/package.nolint.json",
10-
);
11-
const ESLINT_TEMPLATE = readTemplateSync("init/functions/typescript/_eslintrc");
6+
const PACKAGE_TEMPLATE = readTemplateSync("init/functions/typescript/package.json");
7+
const BIOME_TEMPLATE = readTemplateSync("init/functions/typescript/biome.json");
128
const TSCONFIG_TEMPLATE = readTemplateSync("init/functions/typescript/tsconfig.json");
13-
const TSCONFIG_DEV_TEMPLATE = readTemplateSync("init/functions/typescript/tsconfig.dev.json");
149
const INDEX_TEMPLATE = readTemplateSync("init/functions/typescript/index.ts");
1510
const GITIGNORE_TEMPLATE = readTemplateSync("init/functions/typescript/_gitignore");
1611

1712
export async function setup(setup: any, config: any): Promise<any> {
18-
setup.functions.lint =
19-
setup.functions.lint ||
20-
(await confirm({
21-
message: "Do you want to use ESLint to catch probable bugs and enforce style?",
22-
default: true,
23-
}));
24-
2513
const cbconfig = configForCodebase(setup.config.functions, setup.functions.codebase);
26-
cbconfig.predeploy = [];
27-
if (setup.functions.lint) {
28-
cbconfig.predeploy.push('npm --prefix "$RESOURCE_DIR" run lint');
29-
cbconfig.predeploy.push('npm --prefix "$RESOURCE_DIR" run build');
30-
await config.askWriteProjectFile(
31-
`${setup.functions.source}/package.json`,
32-
PACKAGE_LINTING_TEMPLATE.replace(
33-
"{{RUNTIME}}",
34-
supported.latest("nodejs").replace("nodejs", ""),
35-
),
36-
);
37-
await config.askWriteProjectFile(`${setup.functions.source}/.eslintrc.js`, ESLINT_TEMPLATE);
38-
// TODO: isn't this file out of date now?
39-
await config.askWriteProjectFile(
40-
`${setup.functions.source}/tsconfig.dev.json`,
41-
TSCONFIG_DEV_TEMPLATE,
42-
);
43-
} else {
44-
cbconfig.predeploy.push('npm --prefix "$RESOURCE_DIR" run build');
45-
await config.askWriteProjectFile(
46-
`${setup.functions.source}/package.json`,
47-
PACKAGE_NO_LINTING_TEMPLATE.replace(
48-
"{{RUNTIME}}",
49-
supported.latest("nodejs").replace("nodejs", ""),
50-
),
51-
);
52-
}
14+
cbconfig.predeploy = [
15+
'npm --prefix "$RESOURCE_DIR" run lint',
16+
'npm --prefix "$RESOURCE_DIR" run build',
17+
];
5318

19+
const runtime = supported.latest("nodejs").replace("nodejs", "");
20+
await config.askWriteProjectFile(
21+
`${setup.functions.source}/package.json`,
22+
PACKAGE_TEMPLATE.replace("{{RUNTIME}}", runtime),
23+
);
24+
await config.askWriteProjectFile(`${setup.functions.source}/biome.json`, BIOME_TEMPLATE);
5425
await config.askWriteProjectFile(`${setup.functions.source}/tsconfig.json`, TSCONFIG_TEMPLATE);
55-
5626
await config.askWriteProjectFile(`${setup.functions.source}/src/index.ts`, INDEX_TEMPLATE);
5727
await config.askWriteProjectFile(`${setup.functions.source}/.gitignore`, GITIGNORE_TEMPLATE);
5828
await askInstallDependencies(setup.functions, config);

templates/init/functions/javascript/_eslintrc

Lines changed: 0 additions & 28 deletions
This file was deleted.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"$schema": "https://biomejs.dev/schemas/latest/schema.json",
3+
"formatter": {
4+
"enabled": true,
5+
"indentStyle": "space"
6+
},
7+
"linter": {
8+
"enabled": true,
9+
"rules": {
10+
"recommended": true
11+
}
12+
}
13+
}
Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,28 @@
1-
/**
2-
* Import function triggers from their respective submodules:
3-
*
4-
* const {onCall} = require("firebase-functions/v2/https");
5-
* const {onDocumentWritten} = require("firebase-functions/v2/firestore");
6-
*
7-
* See a full list of supported triggers at https://firebase.google.com/docs/functions
8-
*/
1+
import { setGlobalOptions } from "firebase-functions";
2+
import * as logger from "firebase-functions/logger";
3+
import { onRequest } from "firebase-functions/v2/https";
94

10-
const {setGlobalOptions} = require("firebase-functions");
11-
const {onRequest} = require("firebase-functions/https");
12-
const logger = require("firebase-functions/logger");
5+
// Start writing functions:
6+
// https://firebase.google.com/docs/functions
137

14-
// For cost control, you can set the maximum number of containers that can be
15-
// running at the same time. This helps mitigate the impact of unexpected
16-
// traffic spikes by instead downgrading performance. This limit is a
17-
// per-function limit. You can override the limit for each function using the
18-
// `maxInstances` option in the function's options, e.g.
19-
// `onRequest({ maxInstances: 5 }, (req, res) => { ... })`.
208
// NOTE: setGlobalOptions does not apply to functions using the v1 API. V1
219
// functions should each use functions.runWith({ maxInstances: 10 }) instead.
2210
// In the v1 API, each function can only serve one request per container, so
2311
// this will be the maximum concurrent request count.
24-
setGlobalOptions({ maxInstances: 10 });
12+
setGlobalOptions({
13+
// For cost control, you can set the maximum number of containers that can be
14+
// running at the same time. This helps mitigate the impact of unexpected
15+
// traffic spikes by instead downgrading performance. This limit is a
16+
// per-function limit. You can override the limit for each function using the
17+
// `maxInstances` option in the function's options, e.g.
18+
// `onRequest({ maxInstances: 5 }, (req, res) => { ... })`.
19+
maxInstances: 10,
20+
// Tip: event-driven triggers must run in the same region as the Firebase
21+
// services they listen to (Firestore, Storage, etc.).
22+
region: "us-central1",
23+
});
2524

26-
// Create and deploy your first functions
27-
// https://firebase.google.com/docs/functions/get-started
28-
29-
// exports.helloWorld = onRequest((request, response) => {
30-
// logger.info("Hello logs!", {structuredData: true});
31-
// response.send("Hello from Firebase!");
32-
// });
25+
export const helloWorld = onRequest((_request, response) => {
26+
logger.info("Hello from Firebase!", { structuredData: true });
27+
response.send("Hello from Firebase!");
28+
});
Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
11
{
22
"name": "functions",
3-
"description": "Cloud Functions for Firebase",
3+
"type": "module",
4+
"private": true,
5+
"engines": {
6+
"node": "{{RUNTIME}}"
7+
},
8+
"main": "index.js",
49
"scripts": {
10+
"lint": "biome lint .",
11+
"format": "biome format --write .",
512
"serve": "firebase emulators:start --only functions",
613
"shell": "firebase functions:shell",
714
"start": "npm run shell",
815
"deploy": "firebase deploy --only functions",
916
"logs": "firebase functions:log"
1017
},
11-
"engines": {
12-
"node": "{{RUNTIME}}"
13-
},
14-
"main": "index.js",
1518
"dependencies": {
16-
"firebase-admin": "^12.6.0",
17-
"firebase-functions": "^6.0.1"
19+
"firebase-admin": "^13.5.0",
20+
"firebase-functions": "^6.4.0"
1821
},
1922
"devDependencies": {
23+
"@biomejs/biome": "^2.2.5",
2024
"firebase-functions-test": "^3.1.0"
21-
},
22-
"private": true
25+
}
2326
}

0 commit comments

Comments
 (0)