Cloud function fails with "missing ) after argument list at wrapSafe"? - javascript

I'm in the process of splitting my cloud functions in separate files, so as to lazy load some dependencies and reduce cold start.
Basically, I'm trying to replicate Doug's answer from here, but not having to create a separate file for each function.
In my index.js file:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.createStripeCustomer = functions.auth.user().onCreate(async (user) => {
const { createUser } = require('./user/main');
await createUser(user, admin);
});
And in my 'user/main.js' file:
const functions = require('firebase-functions');
const { Stripe } = require('stripe');
const stripe = new Stripe(functions.config().stripe.secret);
const endpointSecret = functions.config().stripe.singing;
const createStripeCustomer = async (user, admin) => {
// Do some stuff
};
module.exports = { createUser: createStripeCustomer };
The intention behind this split, is that I have some functions which require Stripe, and some which do not, hence I don't want them all to load it unnecessarily, but I get an error- "missing ) after argument list".
Any suggestions as to what has gone wrong?

Your solution does not look like the real solution...
Maybe you also fixed something which looked insignificant... Like an extra double quote.
let something = "A"
console.log("hello", something")
See the extra double quote after the variable?
It produces the same error you mentionned.
It is a common error due to code editors just adding thing for you... And if you are like me and look at the keyboard instead of the screen, it is easy not to notice.

Just in case anyone experiences a similar problem, I managed to get it working, simply by changing:
const createStripeCustomer = async (user, admin) => {
// Do some stuff
};
to:
async function createStripeCustomer(user, admin) {
// Do some stuff
};
I have no idea why that was an issue, but it seemed to resolve the problem I had before.

Related

Display cpu info in electron

So I started learning electron and I made a cool app. I wanted to add more things, but I'm kinda stuck. I tried to add cpu name using manufacturer(); in systeminformation. I have no idea what have I done wrong. I'll remind you last time that I'm a complete beginner, so expect me to be kinda dumb.
This is how my div I want to make looks like
<div class="cpu_name">
CPU name: <span id="cpu-name">-</span>
</div>
<div class="cpu_cores">
CPU cores: <span id="cpu-cores">-</span>
</div>
<div class="cpu_temperature">
CPU temperature: <span id="cpu-temperature">-</span>
</div>
</div>
Also, I didn't forget to use script
<script src="./renderer.js" defer type="module"></script>
<script src="./js/window.js" defer type="module"></script>
Next thing I've done was adding it into the renderer.js
I created var linked to the #cpu-name
const CPU_NAME = document.getElementById("cpu-name");
Then I created getCpuName() function
async function getCpuName(){
const name = await app.cpuName();
const cpu_name = name.manufacturer;
updateCpuName(cpu_name);
}
Since I called a updateCpuName() method, I created one
function updateCpuName(cpu__name){
CPU_NAME.innerText = cpu__name;
console.log(cpu__name);
}
Next thing I've done was adding it into the preload.js. I've done the preload.js by tutorial, because I don't really uderstand everything there yet...
This is my whole preload.js script
const os = require("os");
const { ipcRenderer, contextBridge } = require("electron");
const API = {
window:{
close: () => ipcRenderer.send("app/close"),
minimize: () => ipcRenderer.send("app/minimize"),
},
cpuUsage: (data) => ipcRenderer.invoke("cpu/get", data),
cpuName: (data) => ipcRenderer.invoke("cpu/name", data),
}
contextBridge.exposeInMainWorld("app", API);
But this cpuName: (data) => ipcRenderer.invoke("cpu/name", data), is the only important thing here.
Last thing I did was adding it into the index.js.
So I basically created const with systeminformation
const {currentLoad, manufacturer, cpu } = require("systeminformation");
and then made a ipcMain.handle();
ipcMain.handle("cpu/name", async (_, data) => {
const name = await manufacturer();
return name;
});
I know for sure I've done something wrong, but I'm not able to figure out what. It's just fun project I'm working on to get better in it. Thank you for even just reading this ^-^
There is an npm module called systeminformation (https://www.npmjs.com/package/systeminformation) that will help you with this. I have never accessed the CPU using electron or this module, but the module seems very easy to use and is very well documented.
Please also look at the "Known Issues" section of the module readme. Some additional dependencies are required for checking CPU temperature, so you might want to look at that too!

Firebase 9 - how to chain 'addDoc' or similar to a 'collection'?

Previously in Firebase you could add a document like this:
const myNewDoc = await db.collection('some-collection-name').add({ //Document details here... });
With the introduction of Firebase 9 this no longer works.
Instead of .add I think I am supposed to use an imported .addDoc method.
But it seems I cannot chain .addDoc onto .collection.
If I try to do something like this:
const myNewDoc = await db.collection('some-collection-name').addDoc({ //Document details here... });
TypeScript throws this error:
Property 'addDoc' does not exist on type 'CollectionReference<DocumentData>'.ts(2339)
I could create something more verbose like this:
const someCol = collection(db, "some-collection-name");
const newDoc = await addDoc(someCol, {
//Document details here...
});
But I would rather "chain" it like before.
Is that possible? How would it be done?
And should I even be using .addDoc? Or something else?
The addDoc() is a top level function in Modular SDK. Try refactoring your code like this:
import { collection, addDoc } from "firebase/firestore";
const newDoc = await addDoc(collection(db, "some-collection-name"), {
// Document Data
});
console.log("Document written with ID: ", newDoc.id);
The documentation has examples of both name-spaced and the new syntax.
If you are using compat version to use older syntax then you would have to use add() itself.

Why is a new instance of a object undefined?

I am unable to use the same instance of an object in another java-script file using nodejs.
I'm working on a bot for telegram. Because the file gets large and chaotic, i would like to split the functions of my bot into a few extra js files. But i don't know any way how to share the same instance of an object between multiple javascript files.
///////////////////////8Ball File
const {eightBall} = require("./main");
const ballBot = myAwseomeBot;
function eightBall() {
ballBot.onText(/\/8ball/, (msg, callback) => {
let ranNum = Math.floor(Math.random() * 15) + 1;
const chatId = msg.chat.id;
const reply_to_message_id = msg.message_id;
console.log(ranNum);
switch (ranNum) {
case 1:
ballBot.sendMessage(chatId, "Ja");
break;
}
})
}
//main file
let myAwesomeBot = new TelegramBot(botToken, {polling:true});
exports.myAwesomeBot = myAwesomeBot;
ballBot.onText(/\/8ball/, (msg, callback) => {
^
TypeError: Cannot read property 'onText' of undefined
It isn't shown in your code here, but you probably have a cyclic dependency, where A requires B, and B requires A.
The simplest solution relevant to your use case is to define and implement commands for your bot in additional files, and let your bot file attach / consume them:
8ball.js
import { telegram stuff } from 'wherever';
export myCommand1 = {
pattern: /\/8ball/,
eventName: 'ontext',
callback: (msg, msgCallback) => { /* use "this" as if it were the bot instance */};
};
main.js
import .... from ....;
import { myCommand1 } from '8ball';
...
bot.onText(myCommand1.pattern, myCommand1.callback.bind(bot));
...
There are probably other bot class methods more suited for attaching generic event handlers/listeners, and also other methods of specifying your module exports, but the idea is that your command files don't need to import the bot file. I have not researched the telegram bot API so it may have some manner of delegating the bot instance when attaching an event handler. If so, use it!
Did you check that ballBot was defined?
Try to remove the brackets when requiring the main file. I would also suggest using the Singleton pattern if you want to share the same instance across your code.
Could it be that there is a typo on line 2? Should be
myAwesomeBot not myAwseomeBot.
const ballBot = myAwseomeBot;

Evalute JS file with template strings from another file

I would like to make use of a function called executeJavaScript() from the Electron webContents API. Since it is very close to eval() I will use this in the example.
The problem:
I have a decent sized script but it is contained in a template string.
Expanding this app, the script could grow a lot as a string.
I am not sure what the best practices are for this.
I also understand that eval() is dangerous, but I am interested in the principal of my question.
Basic eval example for my question:
// Modules
const fs = require('fs');
// CONSTANTS
const EXAMPLE_1 = 'EXAMPLE_1';
const EXAMPLE_2 = 'EXAMPLE_2';
const EXAMPLE_3 = 'EXAMPLE_3';
const exampleScriptFunction = require('./exampleScriptFunction');
const exampleScriptFile = fs.readFileSync('./exampleScriptFile.js');
// using direct template string
eval(`console.log(${EXAMPLE_1})`);
// using a method from but this doesnt solve the neatness issue.
eval(exampleScriptFunction(EXAMPLE_2));
// What I want is to just use a JS file because it is neater.
eval(`${exampleScriptFile}`);
exampleScriptFunction.js
module.exports = function(fetchType) {
return `console.log(${fetchType});`;
}
This will allow me to separate the script to a new file
what if I have many more then 1 variable???
exampleScriptFile.js:
console.log(${EXAMPLE_3});
This clearly does not work, but I am just trying to show my thinking.
back ticks are not present, fs loads as string, main file has back ticks.
This does not work. I do not know how else to show what I mean.
Because I am loading this will readFileSync, I figured the es6 template string would work.
This allows me to write a plain js file with proper syntax highlighting
The issue is the variables are on the page running the eval().
Perhaps I am completely wrong here and looking at this the wrong way. I am open to suggestions. Please do not mark me minus 1 because of my infancy in programming. I really do not know how else to ask this question. Thank you.
Assuming your source is stored in exampleScriptFile:
// polyfill
const fs = { readFileSync() { return 'console.log(`${EXAMPLE_3}`);'; } };
// CONSTANTS
const EXAMPLE_1 = 'EXAMPLE_1';
const EXAMPLE_2 = 'EXAMPLE_2';
const EXAMPLE_3 = 'EXAMPLE_3';
const exampleScriptFile = fs.readFileSync('./exampleScriptFile.js');
// What I want is to just use a JS file because it is neater.
eval(exampleScriptFile);
Update
Perhaps I wasn't clear. The ./exampleScriptFile.js should be:
console.log(`${EXAMPLE_3}`);
While what you're describing can be done with eval as #PatrickRoberts demonstrates, that doesn't extend to executeJavaScript.
The former runs in the caller's context, while the latter triggers an IPC call to another process with the contents of the code. Presumably this process doesn't have any information on the caller's context, and therefore, the template strings can't be populated with variables defined in this context.
Relevant snippets from electron/lib/browsers/api/web-contents.js:
WebContents.prototype.send = function (channel, ...args) {
// ...
return this._send(false, channel, args)
}
// ...
WebContents.prototype.executeJavaScript = function (code, hasUserGesture, callback) {
// ...
return asyncWebFrameMethods.call(this, requestId, 'executeJavaScript',
// ...
}
// ...
const asyncWebFrameMethods = function (requestId, method, callback, ...args) {
return new Promise((resolve, reject) => {
this.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', requestId, method, args)
// ...
})
}
Relevant snippets from electron/atom/browser/api/atom_api_web_contents.cc
//...
void WebContents::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "WebContents"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
// ...
.SetMethod("_send", &WebContents::SendIPCMessage)
// ...
}

Expanding upon express.js response module

I'm writing an application where I need two templating languages. Currently, I'm using code like
app.get('/route1', function(req, res) {
res.render('path/to/jade/template' {title: "Express")
})
app.get('route2', function(req, res) {
var _ = require('lodash')
, fs = require('fs')
, template = fs.readFileSync('views/path/to/lodash/template')
res.send ( _.template(template, {title: "Express"}) )
})
I'd really like to move that into another res function, like
res.template('path/to/lodash/template', { data })
While I can just edit the express node_module, that's hardly an elegant solution. Are there any examples of how to do this? Does express.js give you the option to expand on what it already has?
Update:
I've looked into express's app.engine function and have the following code:
app.engine('js', function(path, options, fn) {
var file = fs.readFileSync(path, 'utf-8')
, template = require('lodash').template(file)
console.log(template(options)) // this logs the file how I want
return template(options)
})
While it's logging what I want, nothing seems to be returning to the client. The request just hangs. I've tried return statements such as return function() { return template(options) } and return function(locals) { return template(locals) }, however it doesn't seem to be calling that function, so I believe that syntax is for an older version of express
Also, I'm aware that consolidate.js solves this problem, but if possible I would prefer to solve it without it (or at least know how :)
I got it to work after playing around some. I'd love some comments on my solution :)
The working code is as follows:
app.engine('js', function(path, options, fn) {
var file = require('fs').readFileSync(path, 'utf-8')
var str = require('lodash').template(file, options)
fn(null, str)
})
I still need to add better (some) error handling, probably move the rendering into a readFile callback as opposed to readFileSync, maybe pull out the locals from the options param, but at the very least this works

Categories