Skip to content

Commit

Permalink
Overhaul ext:dev:init (#5498)
Browse files Browse the repository at this point in the history
* Overhaul ext:dev:init

* Lint and changelog

* Typo fix
  • Loading branch information
joehan authored Feb 10, 2023
1 parent 16e5e43 commit 7258fca
Show file tree
Hide file tree
Showing 14 changed files with 172 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- Web frameworks deploys can once again bundle local NPM dependencies (#5440)
- Catches error when attempting to deploy without a project (#5415)
- Fixes a number of issues and outdated dependencies in templates for `init --only functions` and `ext:dev:init`
- Adds integration tests and useful scripts to the extension directory created by `ext:dev:init`.
- Support private network access (CORS-RFC1918) in Firestore Emulator (#4227)
- Fix some edge cases where Emulator UI cannot reach the emulators (#912)
- Fix various accessibility and usability issues in Emulator UI.
Expand Down
45 changes: 45 additions & 0 deletions src/commands/ext-dev-init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ const FUNCTIONS_ROOT = path.resolve(__dirname, "../../templates/init/functions/"

function readCommonTemplates() {
return {
integrationTestFirebaseJsonTemplate: fs.readFileSync(
path.join(TEMPLATE_ROOT, "integration-test.json"),
"utf8"
),
integrationTestEnvTemplate: fs.readFileSync(
path.join(TEMPLATE_ROOT, "integration-test.env"),
"utf8"
),
extSpecTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "extension.yaml"), "utf8"),
preinstallTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "PREINSTALL.md"), "utf8"),
postinstallTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "POSTINSTALL.md"), "utf8"),
Expand Down Expand Up @@ -106,10 +114,18 @@ async function typescriptSelected(config: Config): Promise<void> {
"utf8"
);
const indexTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "typescript", "index.ts"), "utf8");
const integrationTestTemplate = fs.readFileSync(
path.join(TEMPLATE_ROOT, "typescript", "integration-test.ts"),
"utf8"
);
const gitignoreTemplate = fs.readFileSync(
path.join(TEMPLATE_ROOT, "typescript", "_gitignore"),
"utf8"
);
const mocharcTemplate = fs.readFileSync(
path.join(TEMPLATE_ROOT, "typescript", "_mocharc"),
"utf8"
);
const eslintTemplate = fs.readFileSync(
path.join(FUNCTIONS_ROOT, "typescript", "_eslintrc"),
"utf8"
Expand All @@ -126,7 +142,20 @@ async function typescriptSelected(config: Config): Promise<void> {
await config.askWriteProjectFile("PREINSTALL.md", templates.preinstallTemplate);
await config.askWriteProjectFile("POSTINSTALL.md", templates.postinstallTemplate);
await config.askWriteProjectFile("CHANGELOG.md", templates.changelogTemplate);
await config.askWriteProjectFile("functions/.mocharc.json", mocharcTemplate);
await config.askWriteProjectFile("functions/src/index.ts", indexTemplate);
await config.askWriteProjectFile(
"functions/integration-tests/integration-test.spec.ts",
integrationTestTemplate
);
await config.askWriteProjectFile(
"functions/integration-tests/firebase.json",
templates.integrationTestFirebaseJsonTemplate
);
await config.askWriteProjectFile(
"functions/integration-tests/extensions/greet-the-world.env",
templates.integrationTestEnvTemplate
);
if (lint) {
await config.askWriteProjectFile("functions/package.json", packageLintingTemplate);
await config.askWriteProjectFile("functions/.eslintrc.js", eslintTemplate);
Expand All @@ -146,6 +175,10 @@ async function typescriptSelected(config: Config): Promise<void> {
*/
async function javascriptSelected(config: Config): Promise<void> {
const indexTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "javascript", "index.js"), "utf8");
const integrationTestTemplate = fs.readFileSync(
path.join(TEMPLATE_ROOT, "javascript", "integration-test.js"),
"utf8"
);
const packageLintingTemplate = fs.readFileSync(
path.join(TEMPLATE_ROOT, "javascript", "package.lint.json"),
"utf8"
Expand Down Expand Up @@ -176,6 +209,18 @@ async function javascriptSelected(config: Config): Promise<void> {
await config.askWriteProjectFile("POSTINSTALL.md", templates.postinstallTemplate);
await config.askWriteProjectFile("CHANGELOG.md", templates.changelogTemplate);
await config.askWriteProjectFile("functions/index.js", indexTemplate);
await config.askWriteProjectFile(
"functions/integration-tests/integration-test.spec.js",
integrationTestTemplate
);
await config.askWriteProjectFile(
"functions/integration-tests/firebase.json",
templates.integrationTestFirebaseJsonTemplate
);
await config.askWriteProjectFile(
"functions/integration-tests/extensions/greet-the-world.env",
templates.integrationTestEnvTemplate
);
if (lint) {
await config.askWriteProjectFile("functions/package.json", packageLintingTemplate);
await config.askWriteProjectFile("functions/.eslintrc.js", eslintTemplate);
Expand Down
2 changes: 2 additions & 0 deletions templates/extensions/integration-test.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GREETING=Hello
LOCATION=us-central1
14 changes: 14 additions & 0 deletions templates/extensions/integration-test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"emulators": {
"functions": {
"port": 5001
},
"ui": {
"enabled": true
},
"singleProjectMode": true
},
"extensions": {
"greet-the-world": "../.."
}
}
19 changes: 14 additions & 5 deletions templates/extensions/javascript/WELCOME.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
This directory now contains the source files for a simple extension called **greet-the-world**. To try out this extension right away, install it in an existing Firebase project by running:
This directory now contains the source files for a simple extension called **greet-the-world**. You can try it out right away in the Firebase Emulator suite - just naviagte to the integration-test directory and run:

`firebase ext:install . --project=<project-id>`
`firebase emulators:start --project=<project-id>`

If you want to jump into the code to customize your extension, then modify **index.js** and **extension.yaml** in your favorite editor. When you're ready to try out your fancy new extension, run:
If you don't have a project to use, you can instead use '--project=demo-test' to run against a fake project.

`firebase ext:install . --project=<project-id>`
The `integration-test` directory also includes an end to end test (in the file integration-test.spec.js) that verifies that the extension responds back with the expected greeting. You can see it in action by running:

As always, in the docs, you can find detailed instructions for creating and testing your extension (including using the emulator!).
`npm run test`

If you want to jump into the code to customize your extension, then modify **index.js** and **extension.yaml** in your favorite editor.

If you want to deploy your extension to test on a real project, go to a Firebase project directory (or create a new one with `firebase init`) and run:

`firebase ext:install ./path/to/extension/directory --project=<project-id>`
`firebase deploy --only extensions`

You can find more information about building extensions in the publisher docs: https://firebase.google.com/docs/extensions/alpha/overview-build-extensions
13 changes: 13 additions & 0 deletions templates/extensions/javascript/integration-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const axios = require("axios");
const chai = require("chai");

describe("greet-the-world", () => {
it("should respond with the configured greeting", async () => {
const expected = "Hello World from greet-the-world";

const httpFunctionUri = "http://localhost:5001/demo-test/us-central1/ext-greet-the-world-greetTheWorld/";
const res = await axios.get(httpFunctionUri);

return chai.expect(res.data).to.eql(expected);
}).timeout(10000);
});
10 changes: 8 additions & 2 deletions templates/extensions/javascript/package.lint.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,16 @@
"eslint": "^8.15.1",
"eslint-plugin-promise": "^6.0.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-import": "^2.25.4"
"eslint-plugin-import": "^2.25.4",
"axios": "^1.3.2",
"chai": "^4.3.7",
"mocha": "^10.2.0"
},
"scripts": {
"lint": "./node_modules/.bin/eslint --max-warnings=0 .."
"lint": "./node_modules/.bin/eslint --max-warnings=0 ..",
"lint:fix": "./node_modules/.bin/eslint --max-warnings=0 --fix ..",
"mocha": "mocha '**/*.spec.js'",
"test": "(cd integration-tests && firebase emulators:exec 'npm run mocha' -P demo-test)"
},
"private": true
}
9 changes: 9 additions & 0 deletions templates/extensions/javascript/package.nolint.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,14 @@
"firebase-admin": "^11.5.0",
"firebase-functions": "^4.2.0"
},
"devDependencies": {
"axios": "^1.3.2",
"chai": "^4.3.7",
"mocha": "^10.2.0"
},
"scripts": {
"mocha": "mocha '**/*.spec.js'",
"test": "(cd integration-tests && firebase emulators:exec 'npm run mocha' -P demo-test)"
},
"private": true
}
23 changes: 18 additions & 5 deletions templates/extensions/typescript/WELCOME.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
This directory now contains the source files for a simple extension called **greet-the-world**. To try out this extension right away, install it in an existing Firebase project by running:
This directory now contains the source files for a simple extension called **greet-the-world**. You can try it out right away in the Firebase Emulator suite: first, compile your code by running:

`npm run build --prefix=functions && firebase ext:install . --project=<project-id>`
`npm run build --prefix=functions`

If you want to jump into the code to customize your extension, then modify **index.ts** and **extension.yaml** in your favorite editor. When you're ready to try out your fancy new extension, run:
Then, navigate to the `functions/integration-test` directory and run:

`npm run build --prefix=functions && firebase ext:install . --project=<project-id>`
`firebase emulators:start --project=<project-id>`

As always, in the docs, you can find detailed instructions for creating and testing your extension (including using the emulator!).
If you don't have a project to use, you can instead use '--project=demo-test' to run against a fake project.

The `integration-test` directory also includes an end to end test (in the file **integration-test.spec.ts**) that verifies that the extension responds back with the expected greeting. You can see it in action by running:

`npm run test`

If you want to jump into the code to customize your extension, then modify **index.ts** and **extension.yaml** in your favorite editor.

If you want to deploy your extension to test on a real project, go to a Firebase project directory (or create a new one with `firebase init`) and run:

`firebase ext:install ./path/to/extension/directory --project=<project-id>`
`firebase deploy --only extensions`

You can find more information about building extensions in the publisher docs: https://firebase.google.com/docs/extensions/alpha/overview-build-extensions
10 changes: 10 additions & 0 deletions templates/extensions/typescript/_mocharc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"require": "ts-node/register",
"extensions": ["ts", "tsx"],
"spec": [
"integration-tests/**/*.spec.*"
],
"watch-files": [
"src"
]
}
13 changes: 13 additions & 0 deletions templates/extensions/typescript/integration-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import axios from "axios";
import { expect } from "chai";

describe("greet-the-world", () => {
it("should respond with the configured greeting", async () => {
const expected = "Hello World from greet-the-world";

const httpFunctionUri = "http://localhost:5001/demo-test/us-central1/ext-greet-the-world-greetTheWorld/";
const res = await axios.get(httpFunctionUri);

return expect(res.data).to.eql(expected);
}).timeout(10000);
});
13 changes: 11 additions & 2 deletions templates/extensions/typescript/package.lint.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,30 @@
"name": "functions",
"scripts": {
"lint": "eslint \"src/**/*\"",
"lint:fix": "eslint \"src/**/*\" --fix",
"build": "tsc",
"build:watch": "tsc --watch"
"build:watch": "tsc --watch",
"mocha": "mocha '**/*.spec.ts'",
"test": "(cd integration-tests && firebase emulators:exec 'npm run mocha' -P demo-test)"
},
"main": "lib/index.js",
"dependencies": {
"firebase-admin": "^11.5.0",
"firebase-functions": "^4.2.0"
},
"devDependencies": {
"@types/chai": "^4.3.4",
"@types/mocha": "^10.0.1",
"@typescript-eslint/eslint-plugin": "^5.12.0",
"@typescript-eslint/parser": "^5.12.0",
"eslint": "^8.15.1",
"eslint-plugin-import": "^2.26.0",
"eslint-config-google": "^0.14.0",
"typescript": "^4.9.0"
"typescript": "^4.9.0",
"axios": "^1.3.2",
"chai": "^4.3.7",
"mocha": "^10.2.0",
"ts-node": "^10.4.0"
},
"private": true
}
12 changes: 10 additions & 2 deletions templates/extensions/typescript/package.nolint.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,23 @@
"name": "functions",
"scripts": {
"build": "tsc",
"build:watch": "tsc --watch"
"build:watch": "tsc --watch",
"mocha": "mocha '**/*.spec.ts'",
"test": "(cd integration-tests && firebase emulators:exec 'npm run mocha' -P demo-test)"
},
"main": "lib/index.js",
"dependencies": {
"firebase-admin": "^11.5.0",
"firebase-functions": "^4.2.0"
},
"devDependencies": {
"typescript": "^4.9.0"
"@types/chai": "^4.3.4",
"@types/mocha": "^10.0.1",
"typescript": "^4.9.0",
"axios": "^1.3.2",
"chai": "^4.3.7",
"mocha": "^10.2.0",
"ts-node": "^10.4.0"
},
"private": true
}
5 changes: 4 additions & 1 deletion templates/init/functions/javascript/_eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ module.exports = {
es6: true,
node: true,
},
parserOptions: {
"ecmaVersion": 2018,
},
extends: [
"eslint:recommended",
"google",
Expand All @@ -14,7 +17,7 @@ module.exports = {
},
overrides: [
{
files: ["*.spec.*"],
files: ["**/*.spec.*"],
env: {
mocha: true,
},
Expand Down

0 comments on commit 7258fca

Please sign in to comment.