I'm writing an Android app that stores data in a Firebase Firestore and manipulates it with Firebase Cloud Functions. I've written the server code using kotlin2js. The Cloud Function throws an undefined error when trying to iterate over the properties of a simple object.
Why am i getting this error?
How do I process the data stored in the object?
1) MainActivity.kt
package com.srsly.wtf
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import com.google.firebase.firestore.FirebaseFirestore
import kotlinx.android.synthetic.main.activity_main.button
class MainActivity : AppCompatActivity() {
override fun onCreate(bundle: Bundle?) {
super.onCreate(bundle)
setContentView(R.layout.activity_main)
button.setOnClickListener { _ -> upload() }
}
fun upload() {
FirebaseFirestore.getInstance().collection("test")
.add(TestClass())
.addOnSuccessListener { ref ->
ref.addSnapshotListener { snapshot, _ ->
button.text = snapshot.toObject(TestClass::class.java).foo
}
}
}
data class TestClass(val foo = "bar")
}
2) index.kt
import kotlin.js.Promise
external fun require(module: String): dynamic
external val exports: dynamic
fun main(args: Array<String>) {
val functions = require("firebase-functions")
val admin = require("firebase-admin")
admin.initializeApp(functions.config().firebase)
exports.receiveObj = functions.firestore.document("/test/{testId}").onWrite { event ->
val obj = event.data.data().unsafeCast<Map<String, String>>()
obj.entries.forEach{
val newObj = js("({})")
newObj[it.key.toUpperCase()] = it.value.toUpperCase()
event.data.ref.set(newObj)
}
}
}
3) index.js
(function (_, Kotlin) {
'use strict';
var Unit = Kotlin.kotlin.Unit;
function main$lambda(event) {
var obj = event.data.data();
var tmp$;
tmp$ = obj.entries.iterator();
while (tmp$.hasNext()) {
var element = tmp$.next();
var newObj = {};
newObj[element.key.toUpperCase()] = element.value.toUpperCase();
event.data.ref.set(newObj);
}
return Unit;
}
function main(args) {
var functions = require('firebase-functions');
var admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.receiveObj = functions.firestore.document('/test/{testId}').onWrite(main$lambda);
}
_.main_kand9s$ = main;
main([]);
Kotlin.defineModule('index', _);
return _;
}(module.exports, require('kotlin')));
4) build.gradle for the functions project
buildscript {
ext.kotlin_version = '1.2.21'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
version '1.0-SNAPSHOT'
apply plugin: 'java'
apply plugin: 'kotlin2js'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-js:$kotlin_version"
testCompile group: 'junit', name: 'junit', version: '4.12'
}
compileKotlin2Js.kotlinOptions {
moduleKind = "commonjs"
outputFile = "functions/index.js"
}
5) the error message from the firebase functions log
TypeError: Cannot read property 'iterator' of undefined
at main$lambda (/user_code/index.js:7:23)
at Object.<anonymous> (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:59:27)
at next (native)
at /user_code/node_modules/firebase-functions/lib/cloud-functions.js:28:71
at __awaiter (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:24:12)
at cloudFunction (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:53:36)
at /var/tmp/worker/worker.js:695:26
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
Related
I'm quite new to Javascript. I had to switch my project to type "Module" because an import required it. However it totally broke my code.
I am using an AutoLoader to load in all my created classes:
const modules = new Autoloader(path.resolve('./modules'), {
ignore: [
'command.js',
'service.js',
'event.js'
]
});
Normally when I printed out modules it would look like:
{ commands: { invite: class Invite extends Command } }
Now it doesnt recognize the class any more:
{ commands: { invite: undefined } }
The autoloader loads all the classes out (for example) my commands directory.
const api = require('../../api');
const Command = require('./command');
class Invite extends Command {
prefix = '/invite';
handle(message) {
let args = this.stripWithoutLower(message);
if (message.isGroupMsg !== this.groupOnly) {
return;
}
if (typeof args[1] !== 'undefined') {
let inviteCode = args[1].split('/');
if (typeof inviteCode[3] !== 'undefined') {
this.client.joinGroup(inviteCode[3]);
}
}
}
}
module.exports = Invite;
Normally I would use module.exports to export the class. Inside my main.js file I would them loop through the classes I've autoloaded to initiate them. For example:
const commandList = [];
Object.keys(modules['commands']).forEach(key => {
commandList.push(new modules['commands'][key](client));
});
The above coded was working until I had to switch everything to type "Module". Im very new to javascript forgive me about any mis typings.
I've read online that I had to switch module.exports to exports.default = Invite; or to export Class. Unfortunately both didn't worked.
What error am I getting:
TypeError: modules.commands[key] is not a constructor
I'm new to Angular and Nodejs. I'm currently developing a Web Application using Angular 5. I want to create a node module and publish it to npm and use it in my app. This module should read from an xml file to create some objects. It always gives me the same error ( fs_1.readFile is not a function). I don't know if it 's possible to read from xml inside the node module.
I'm trying to create an npm package, within this package there will be an xml file. inside one of the classes of this package I want to read the xml file.
Here is screenshot from #types/node module. The function exists
Here is my index.js :
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = require("fs");
const xml_js_1= require("xml-js");
class PasswordsConfiguration{
constructor(){
this.passwords=new Array();
this.companies=new Array();
this._json = undefined;
this.readXML()
}
readXML(){
var name,isFunction, maskAND, maskOR, key, defaultValue,companyName,displayedName;
try{
fs_1.readFile('./passwords-config.xml', 'utf8', (err, data) => {
// just neglect the rest of the code, it doesn#t enter this function.
if (err) {
}
else {
this._json = xml_js_1.xml2js(data, {
compact: true,
nativeType: true,
ignoreDeclaration: true,
ignoreComment: true
});
this._json.Configuration.Passwords.every((password) => {
name =password._attributes.name;
isFunction=Boolean(password._attributes.isFunction);
maskAND = parseInt(password._attributes.maskAND,16);
maskOR = parseInt(password._attributes.maskOR,16);
key = password._attributes.key;
defaultValue = parseInt(password._attributes.defaultValue,16);
this.passwords.push(new Password(name,isFunction, maskAND, maskOR, key, defaultValue));
});
this._json.Configuration.Companies.every((company) => {
companyName =company._attributes.name;
displayedName =company._attributes.displayedName;
this.companies.push(new Company(companyName,displayedName));
});
}
});
}catch(e){
}
}
}
exports.PasswordsConfiguration = PasswordsConfiguration;
Here is the index.d.ts
export declare class PasswordsConfiguration {
private _json:any;
passwords:Array<Password>;
companies:Array<Company>;
constructor();
readXML():void;
}
So is this functionality applicable? What's wrong in the code?
File name Postman.js
"use strict";
define([], function() {
var postManSingleton = (function() {
var postManInstance
, createPostMan = function() {
var events = {};
return {
publish: function(event, payload) {
if(!events.hasOwnProperty(event))
return;
events[event].forEach(function(listener){
listener(payload || {});
});
},
subscribe: function(event, listener) {
if(!events.hasOwnProperty(event))
events[event] = [];
var index = events[event].push(listener)-1;
return {
remove: function () {
delete events[event][index];
}
}
}
}
};
return {
getInstance: function() {
if(!postManInstance)
postManInstance = createPostMan();
return postManInstance;
}
}
}());
return postManSingleton.getInstance();
});
Importing this file as in index.test.js
import * as Postman from 'postman.js';
How do I mock its publish and subscribe events in jest.
I have tried
jest.mock('Postman.publish', () =>({//some code}))
Error : Cannot find module Postman.publish from 'index.test.js'
Please help how it is possible to mock the above file. Is it even possible?
Your Postman.js is in AMD & Jest does not support AMD. So you need to convert AMD to commonjs.
You can use babel-plugin-transform-amd-to-commonjs for conversion.
Stuck with this one.
I am using laravel elxir with tsify to generate my js. I run the typescript through factor-bundle to split common js modules into a seperate files. I don't think though that will be a problem in this case because everything is in a spec.js
spec.ts
/// <reference path="../../../typings/index.d.ts" />
import "jasmine-jquery";
// #start widgets
import "./widgets/common/widget-factory/test";
factory-widget/index.ts
export class WidgetFactory {
.... this contains a require call to browser.service which i need to mock
}
factory-widget/test.ts
...
import {WidgetFactory} from "./index";
const proxyRequire = require("proxyquire");
it("should output the factory items", ()=> {
proxyRequire('./widgets/browser.service/index',{
"#global": true,
});
}
browser-service.ts
...
export class BrowserService implements IBrowserService{
//details
}
Getting an error Uncaught TypeError: require.resolve is not a function on line 262.
Here is the code ( yeah it's over 20,000 lines ) how else are you supposed to debug this stuff . ¯_(ツ)_/¯
I've looked at Stubbing with proxyquire. I am not holding my breath getting an answer on this one.
Edit: 06-09-2016
Proxquire is needed to overide the require call in the boot method of the WidgetFactory class
In factory-widget/index.ts:
boot(output = true):any {
let required = {};
if (this._sorted.length) {
this._sorted.forEach((key)=> {
if (output) {
console.log(`${this._path}${key}/index`);
// this is where is need to overide the call to require.
required[key] = require(`${this._path}${key}/index`);
}
});
this._sorted.forEach((key)=> {
let dependencies = {},
module = this._factory[key];
if (module.hasOwnProperty(this.dependencyKey)) {
module[this.dependencyKey].map((key)=> {
dependencies[_.camelCase(key)] = this.isService(module) ? new required[key] : key;
});
}
if (this.isTag(module)) {
if (output) {
document.addEventListener("DOMContentLoaded", ()=> {
riot.mount(key, dependencies);
});
}
//console.log(key,dependencies);
}
else {
}
})
}
}
I've added a proxyquireify example to the tsify GitHub repo. It's based on the simple example in the proxyquireify README.md.
The significant parts are the re-definition of require to call proxyquire in foo-spec.ts:
const proxyquire = require('proxyquireify')(require);
require = function (name) {
const stubs = {
'./bar': {
kinder: function () { return 'schokolade'; },
wunder: function () { return 'wirklich wunderbar'; }
}
};
return proxyquire(name, stubs);
} as NodeRequire;
and the configuration of the proxyquire plugin in build.js:
browserify()
.plugin(tsify)
.plugin(proxyquire.plugin)
.require(require.resolve('./src/foo-spec.ts'), { entry: true })
.bundle()
.pipe(process.stdout);
If you build the bundle.js and run it under Node.js, you should see that the message written to the console includes strings returned by the functions in the stubbed ./bar module.
I'm looking to use https://github.com/flatiron/nconf in the browser. I have tried to use it with browserify but because nconf calls fs.readdirSync when it is required to scan directories for configuration, it fails in the browser.
// config.js
'use strict';
var nconf = require('nconf'); // this triggers the fs.readdirSync
var globalConfig = { my: { global: 1 }};
nconf.use('global', { type: 'literal', store: globalConfig });
var envConfig = { my: { env: 2 }};
nconf.use('env', { type: 'literal', store: envConfig });
module.exports = nconf;
Is it possible to use some sort of browserify transform (I didn't see a way to make it force the use of BRFS in nconf) or a way to use nconf (or some other similar library) to manage client side configuration?
If not nconf itself, then just something that would allow me to do something similar to this:
config.load('user-settings', { my : { user: 1 } });
config.load('global-settings', { my: { global: 2 } } );
config.get('my.user'); // 1
config.get('my.global'); // 2
config.unload('global-settings');
config.get('my.global'); // undefined
I recently had this issue myself. I decided to just put together my own config file, rather than pull in another library. here's what I ended up with:
/*
This file determines which environment we're in, and provides the app with the appropriate config
*/
export const defaults = {
searchURI: 'http://www.google.com/',
anotherURI: 'https://stackoverflow.com/',
};
export const dev = {
searchURI: 'https://www.bing.com/',
};
export const test = {
searchURI: 'https://www.yahoo.com/',
};
export const prod = {
searchURI: 'https://duckduckgo.com/',
};
const config = () => {
switch (process.env.YOUR_ENV_NAME) {
case 'dev':
return dev;
case 'test':
return test;
default:
return prod;
}
};
export default {
...defaults,
...config(),
};
using this pattern, you can import config just like you would nconf:
import config from './path/to/above/file.js';
const { searchURI, anotherURI } = config;
// OR
const searchURI = config.searchURI;
const anotherURI = config.anotherURI;