Using a Node.js class in Cloud Functions for Firebase - node.js

I am a new to Node.js and Firebase.
I have successfully tried to deploy some Cloud Functions to test them a bit.
I have a Node.js project in which I have a class defined as:
import * as Api from './api';
export default class MyClass {
constructor(props) {[...]}
someFunction(props) {
return Api.someOtherFunction(props.arg1).then([..]).catch([..]);
}
}
In the Api code I use the firebase admin SDK and I work with the real time database.Ex.:
ref.child(`users/${userId}`).set({
id: userId,
arg1: arg1,
arg2: arg2
});
Now, the problem is that I would like to use MyClass in a cloud function.
I have read a lot about ES6 in Cloud Functions, too (ex.: here), but I am not able to get rid of the error message
SyntaxError: Unexpected token import
I have tried to convert to require statements but I am not able to require my local module where MyClass is.
I don't care if it will be a Node.js local module or simply some classes in clear hierarchical structure.
What I would like to ask is if there is a specific documentation about this situation (I have searched a lot for it) and/or if I am following the right way to structure my project.
If the answer is "NO", please give me some tips on how to structure it.

Cloud Functions (node.js) currently does not support the ES6 import syntax, you have to use require().
The examples in the article you linked are using Babel to convert ES6 to ES5. Even if you convert your import statements to require() you're going to encounter the fact that ES5 does not support the class syntax. If you want to do what the article it doing, follow the steps to get Babel converting your ES6 script to ES5 before sending it to Firebase Cloud.

Related

import twilio's Authy library in nest js

we usually use below statement to use authy library in node file using js ,mostly by require statement !
const authy = require('authy')('API KEY');
I've moved my code to nest eco system and now How should i do the same using typescript ,as i also want to pass API Key to it ?
I've tried below code as well ,but still it's not working
import { authy } from 'authy'(API KEY)
suggest something !
I have faced a similar issue in my NestJS project when using twillio library.
Currently, I have resolved this by importing it this way:
import authy = require('authy');
If, this doesn't work for you (for any reason e.g. TypeScript compile error), then can you try the following import statement?
import * as Authy from 'authy';
Also, let me know which one works for you.

Conditional import/export when using different environment

I'm currently developing a Lambda function using node14 on AWS, but I have an issue when I want to develop it locally.
In my dev environment I have a corporate proxy needed to connect to AWS. In this case, I use aws-sdk-proxy library. However, I don't want to use this package while in production (as Lambda already has the aws-sdk injected in lambda core).
So, I created this snippet to perform the switch between the 2 environments:
// aws.js
import AWSPROD from 'aws-sdk'
import AWSDEV from 'aws-sdk-proxy'
import config from '../lib/Config.js'
import logger from './logger.js'
let AWS = null
if (config.get('ENVIRONMENT') === 'dev') {
logger.debug('[DEV] Using aws-sdk-proxy')
AWS = AWSDEV
} else {
AWS = AWSPROD
}
export default AWS
Not so clean, but it works. With this code, I can perform this:
import AWS from './aws.js'
Now the problem is that this code implies that I must provide aws-sdk-proxy into the "prod" dependencies of my package.json.
I think it breaks performance of the lambda as the code raised 9Mo (2Mo without), but I wish to keep this way of calling "AWS" SDK [the 2d code block].
I tried to use required or dynamic import but none of these solutions work.
Do you have any advice to improve my code?
PS:
The code is transpiled to ES5 using Babel to fit Lambda requirements
aws-sdk-proxy library must stay in devDependencies as it's a dev dependency

React Native - Clear Async Storage Script

I'm currently building a react native app which uses async storage. I've got conditionals within the components to decide whether to make requests to the API or use the data stored in memory. So to test out these conditionals I regularly have to clear the AsyncStorage using AsyncStorage.clear().
This works if I have it in one of the components, however it would be more practical to have it in a seperate script - which brings me to my question:
I want to have a script as below:
import AsyncStorage from '#react-native-community/async-storage';
AsyncStorage.clear();
console.log('STORAGE CLEARED');
and then run it using a command like node clearStorage.js (and later an npm script).
However I'm getting an error saying 'Cannot use import statement outside a module'.
Am I missing anything glaringly obvious/trying to do something I shouldn't? I've tried changing the file type to .mjs with no luck.
If you need to do this, you can't use a nodejs script because the node script will never get to the native side, because async-storage is a native library and it connects directly to Android or IOS.
Another solution may be at the start of the application, you can run that code, or create a Button just for dev mode and when click clean the data.
and the error 'Cannot use import statement outside a module'. it's because nodeJs don't understand the syntax import AsyncStorage from '#react-native-community/async-storage'; they need a transpiler like babel.

Firebase docs reference unknown module

Firebase has this piece of information here at https://firebase.google.com/docs/functions/locations:
Client-side location selection for callable functions Regarding the callable function, client callable setups should follow the same guidelines as HTTP functions. The client can also specify a region, and must do so if the function runs in any region other than us-central1.
To set regions on the client, specify the desired region at
initialization:
var functions = firebase.app().functions('us-central1');
I've been trying to find which node module firebase is referring to but I have had no luck.
I know that it is not 'firebase-admin' or 'firebase-functions' but thats about it.
Anyone have any ideas what this might be referring to?
Edit:
I have now also tried using this with the imports require('firebase') and require('firebase/app') (as suggested) but neither of those seem to work. I also tried generating the app with const app = firebase.initializeApp({}); and then running app.functions("region") or app().functions("region") but i keep receiving TypeErrors saying functions is not a function and app is not a function respectively.
firebase.app().functions('us-central1'); is a part of the firebase-js-sdk. With source code documented on GitHub
NPM component is #firebase/functions, that is documented on the npmjs.com.
However, it is not intended for standalone usage, and should be used along with package Firebase.
You can install it using:
$ npm i firebase

How do I mix Typescript namespaces with External modules when "Don't do it" is not an option

Situation
I have a Typescript app written using namespaces. I want to move some of this logic (Google OAuth) out of the client and into a node service. I have created a nearly complete project for that here.
This new project has a node component that will make authorisation requests to google using a secret key and a client component that can be re-used by other applications that will communicate with the server. I also have a testHarness app that uses this client to test it and make sure that I can use it in a namespace based application.
I have some shared interfaces that both the client and server consume.
I want my client code to be usable in projects that use externam modules and namespaces - i.e. my existing project.
It must be possible
I have read in many places
Do not use "namespaces" in external modules.
Don't do this.
Seriously. Stop.
Such as on this answer but I am still convinced that this must be possible. The reason that I think this is that in my project I have a dependency on RxJs. This project in my node_modules folder is used by both the client and the server.
What I have tried
In my project I have a contracts.d.ts file that I want to share between both the client and the server.
StackOverflow
I looked at this question:
Typescript es6 import module "File is not a module error"
And made my contracts look like this:
// test.js - exporting es6
export module App {
export class SomeClass {
getName(): string {
return 'name';
}
}
export class OtherClass {
getName(): string {
return 'name';
}
}
}
and then tried the various import methods listed:
import * as app1 from "./test";
import app2 = require("./test");
import {App} from "./test";
I got each of these to work so that my server AND client compiled correctly but then as soon as I tried to compile my testHarness app - that uses namespaces - it failed:
src/testHarness/testHarness.ts(4,38): error TS2304: Cannot find name 'PricklyThistle'.
src/testHarness/testHarness.ts(4,38): error TS2503: Cannot find namespace 'PricklyThistle'.
Copying Declaration Files from node_modules
As I said, I am convinced that this is possible as dependencies that I import into node_modules are used by both my client and server projects and my client can still be used with internal namespaces.
To go down this route I edited a d.ts file in the Rx ts folder and added a new interface. I verified that both client and server could use this interface and that my testHarness app (with namespaces) woudl compile. All was good!
I then copied this edited file into my common folder. I had to rename the module to avoid conflicts but then I get:
src/node/youTubeAuthenticationServer.ts(3,23): error TS2306: File '/src/common/rx.test.d.ts' is not a module.
My edited declaration file looks like:
declare module RxTest {
export interface TestInterface{
propertyOne: string;
propertyTwo: number;
}
}
declare module "rx.test" { export = RxTest; }
Workaround
For now I have just copied the interfaces that are used by both applications. This works and there are only 2 small interfaces so it's not a big deal. It is very anooying though. One of the great things about node is that is uses the same language as the browser. If you can't share code that is not good. I also have other much larger code bases that I want to do similar things with and in these situations copying code will not be a viable solution.
Any new projects I work on I will exlusively use external modules but when working with legacy code this is not always possible.
I really hope someone can help.
Thanks
If find your question a bit confusing, there's too much description and too little examples (code/configuration) of what you have.
Try to do this:
declare module "rx.test" {
export interface TestInterface{
propertyOne: string;
propertyTwo: number;
}
}
If that doesn't work, please edit your question and add the directory structure that you have, the tsconfig.json file(s) that you have, explain how you build (tsc, gulp, etc) and so on.

Resources