My current issue is that I am trying to deploy a basic function to firebase cloud functions however I keep getting two different errors. The first error is about the two parameters having an implicit any type. From what I've read on other posts all I should've needed to do was add the type to fix it which is what I did. This is where I got my second error which I've only found one other post with the same problem online. The solution for that issue involved removing the types from a separate function he had which doesn't really apply to me. This error said "unexpected token :" and is referring to the colons in the parameter type declaration. I don't have lint enabled which most posts about an unexpected token have as a solution and I would prefer not to disable type checking by turning strict off so other than those two solutions I've seen I haven't been able to find anything else. The error appears to be occurring when firebase is trying to parse the function triggers but that still really hasn't helped me much. I'll add all the relevant images and code below that might be helpful. If there's anything else you might want to see I can add it as well. Thanks.
EDIT 2: What also confuses me is that when I don't add the any type to the parameters I'm able to run the emulator and everything works when I test them. I only have problems when I try to deploy.
Current cloud functions index.ts
const functions = require("firebase-functions");
const axios = require("axios");
const admin = require('firebase-admin');
const cors = require('cors')({origin: true});
admin.initializeApp();
const db = admin.firestore();
exports.testFunc = functions.https.onRequest((request: any, response: any) => {
cors(request, response, () => {
response.send(request.body)
})
})
Project package.json
{
"name": "local-business-helper",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"private": true,
"dependencies": {
"@angular/animations": "~13.0.0",
"@angular/cdk": "^13.0.0",
"@angular/common": "~13.0.0",
"@angular/compiler": "~13.0.0",
"@angular/core": "~13.0.0",
"@angular/fire": "^7.2.0",
"@angular/flex-layout": "^13.0.0-beta.36",
"@angular/forms": "~13.0.0",
"@angular/material": "^13.0.0",
"@angular/platform-browser": "~13.0.0",
"@angular/platform-browser-dynamic": "~13.0.0",
"@angular/router": "~13.0.0",
"axios": "^0.26.1",
"firebase-admin": "^10.1.0",
"firebase-functions": "^3.21.2",
"firebase-tools": "^9.23.3",
"geofire-wrapper": "github:tobias74/geofire-js#upgrade-to-v9-modular",
"moment": "^2.29.3",
"moment-timezone": "^0.5.34",
"ngx-google-places-autocomplete": "^2.0.5",
"ngx-material-timepicker": "^5.5.3",
"rxfire": "^6.0.0",
"rxjs": "~7.4.0",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "~13.0.1",
"@angular/cli": "~13.0.1",
"@angular/compiler-cli": "~13.0.0",
"@types/jasmine": "~3.10.0",
"@types/node": "^12.11.1",
"jasmine-core": "~3.10.0",
"karma": "~6.3.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.0.3",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "~1.7.0",
"typescript": "~4.4.3"
}
}
Functions package.json
{
"name": "functions",
"scripts": {
"build": "tsc",
"serve": "npm run build && firebase emulators:start --only functions",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "16"
},
"main": "src/index.ts",
"dependencies": {
"firebase-admin": "^10.0.2",
"firebase-functions": "^3.21.2"
},
"devDependencies": {
"firebase-functions-test": "^0.2.0",
"typescript": "^4.5.4"
},
"private": true
}
Type Error:
src/index.ts:20:47 - error TS7006: Parameter 'request' implicitly has an 'any' type.
20 exports.testFunc = functions.https.onRequest((request, response) => {
src/index.ts:20:56 - error TS7006: Parameter 'response' implicitly has an 'any' type.
20 exports.testFunc = functions.https.onRequest((request, response) => {
Found 2 errors in the same file, starting at: src/index.ts:20
Error: functions predeploy error: Command terminated with non-zero exit code2
Unexpected Token:
Error: Error occurred while parsing your function triggers.
/Users/......../functions/src/index.ts:20
exports.testFunc = functions.https.onRequest((request: Request, response: any) => {
SyntaxError: Unexpected token':'
at Object.compileFunction(node: vm: 352:18)
at wrapSafe(node: internal/modules/cjs/loader:1031:15)
at Module.compile(node: internal/modules/cjs/loader:1065:27)
at Object.Module.extensions.js(node: internal/modules/js/loader:1153:10)
at Module.load(node: internal/modules/cjs/loader:981:32)
at Function.Module._load(node: internal/modules/cjs/loader:822:12)
at Module.require(node: internal/modules/cjs/loader:1005:19)
at require(node: internal/modules/cjs/helpers:102:18)
at loadModule(/usr/local/lib/node_modules/firebase-tools/lib/deploy/functions/runtimes/node/triggerParser.js:10:16)
at /usr/local/lib/node_modules/firebase-tools/lib/deploy/functions/runtimes/node/triggerParser.js:34:21
EDIT: After noticing there was a update I updated functions and the error format slightly changed but it's still the same.
functions: Finished running predeploy script.
functions: ensuring required API cloudfunctions.googleapis.com is enabled...
functions: ensuring required API cloudbuild.googleapis.com is enabled...
functions: required API cloudbuild.googleapis.com is enabled
functions: required API cloudfunctions.googleapis.com is enabled
functions: preparing codebase default for deployment
Error: Failed to load function definition from source: Failed to generate manifest from function source: SyntaxError: Unexpected token':'
CodePudding user response:
As controversial as this may sound, Cloud Functions don't understand TypeScript. In fact, not just Cloud Functions, all JavaScript engines don't understand TypeScript. There is always a need for a compiler to build TypeScript code to JavaScript as you are coding. Then it is the built JS code that will be run and not TypeScript code.
Yes, Cloud Functions for TypeScript is available, and npm run build -- --watch
takes care of updating the built code as you are coding. Cloud Functions actually runs the built JS code and not the TypeScript code.
The problem with your setup is that the entry point of Cloud Functions is a .ts
file and not .js
. In your package.json for Functions, you have
"main": "src/index.ts"
You have to change it to:
"main": "lib/index.js"
That way the entry point of Cloud Functions will be a JavaScript file, and also, will be the JavaScript that was built from your TypeScript code. lib/index.js
is used because, by default, that is where the tsc
command will build your src/index.ts
file into.
You can check .gitignore
and notice that the lib
folder is included (because its contents always change in every build and shouldn't enter version control). Also notice that there is an index.js.map
file included in your lib
folder too. In fact, for every TypeScript file in your src
folder, a corresponding .js
and .js.map
file is created in your lib
folder.