Left-hand side of assignment expression cannot be a constant or a read-only property - express

When I use this line on my Express server, it works well in TypeScript 1.x
mongoose.Promise = global.Promise;
( The usage of mongoose.Promise = global.Promise; is from the mongoose document )
After updating to TypeScript 2.x, it shows this error in the terminal, and won't let me start the server.
Left-hand side of assignment expression cannot be a constant or a
read-only property.
How can I solve this? Thanks

This is because in es6 all module's variables are considered constants.
https://github.com/Microsoft/TypeScript/issues/6751#issuecomment-177114001
In TypeScript 2.0 the bug (of not reporting this error) was fixed.
Since mongoose is still using the commonjs - var mongoose = require("mongoose") - not the es6 import syntax (which is used in the typings), you can suppress the error by assuming the module is of type any.
WORKAROUND:
(mongoose as any).Promise = global.Promise;

There is also a way to maintain type-checking and intellisense with this technique.
import * as mongoose from "mongoose"; // same as const mongoose = require("mongoose");
type mongooseType = typeof mongoose;
(mongoose as mongooseType).Promise = global.Promise;
// OR
(<mongooseType>mongoose).Promise = global.Promise;
This can be a helpful way to override only certain functions within a module with mock functions without needing a mock framework like jest.mock().

Related

Handlebars with Assemble build returning "not an own property of its parent"

I am experiencing the dreaded not an "own property" of its parent issue when attempting to build my Handlebars project.
I have been down the rabbit hole and seen the many explanations of using #handlebars/allow-prototype-access to allow the issue to be bypassed, however it seems the project does not use a standard implementation of Handlebars...
It seems I am using something called engine-handlebars
Where I would expect to implement that allow-prototype-access change, I see the following:
app.pages('./source/pages/**/*.hbs');
app.engine('hbi', require('engine-handlebars'));
I can't fathom how I am supposed to implement the prototype access with this setup...
It seems, after a bit of trial and error, commenting lines out as I go, that the line app.pages('./source/pages/**/*.hbs'); is actually causing the issue...
When I run the project with this line in, I get the error:
Handlebars: Access has been denied to resolve the property "path" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details
[10:54:49] ERROR - undefined: Cannot read property 'substring' of undefined
The plugin #handlebars/allow-prototype-access works by modifying the Handlebars instance.
const _Handlebars = require('handlebars');
const { allowInsecurePrototypeAccess } = require('#handlebars/allow-prototype-access');
const Handlebars = allowInsecurePrototypeAccess(_Handlebars);
Note that allowInsecurePrototypeAccess does not modify the instance in place, but creates an isolated instance via Handlebars.create() so you must use its return value.
In your case, engine-handlebars exposes the Handlebars instance in different ways depending on what version you are using.
Based on your code you provided, my guess is you are using <1.0.0, but I'll provide methods for adjusting this for all its versions.
engine-handlebars#<0.6.0
Unfortunately these versions don't expose Handlebars in any way, so if you are using this version I recommend upgrading engine-handlebars to a later version.
engine-handlebars#>=0.6.0 <1.0.0
Version 0.6.0 exposed Handlebars as a property on the exported engine function. This is then referenced throughout the library via this.Handlebars.
You can then change this before setting the app.engine() and it should work.
const _Handlebars = require('handlebars');
const { allowInsecurePrototypeAccess } = require('#handlebars/allow-prototype-access');
const engine = require('engine-handlebars');
// elsewhere...
// const app = ...
// Do this *before* setting app.engine
const insecureHandlebars = allowInsecurePrototypeAccess(_Handlebars);
engine.Handlebars = insecureHandlebars;
app.engine('hbi', engine);
engine-handlebars#>=1.0.0
For version 1.0.0 and beyond, you must pass the Handlebars instance yourself.
const Handlebars = require('handlebars');
const engine = require('engine-handlebars')(Handlebars);
Thus you don't need to set anything on engine, you just pass in the modified instance when you need it.
const _Handlebars = require('handlebars');
const { allowInsecurePrototypeAccess } = require('#handlebars/allow-prototype-access');
// elsewhere...
// const app = ...
// Do this *before* setting app.engine
const insecureHandlebars = allowInsecurePrototypeAccess(_Handlebars);
const engine = require('engine-handlebars')(insecureHandlebars);
app.engine('hbi', engine);

How to use scalajs-bundler with client only app

In another question I was advised to use ScalaJS bundler to import NPM dependencies.
I would like to use some Javascript NPM packages in a simple client-only web application. There is an example called static which shows this.
My changes to the example:
Add into build.sbt:
npmDependencies in Compile += "esprima" -> "3.1.3"
Add into Main.scala:
import Esprima._
import JsonToString._
val code = "answer = 42"
val tokens = tokenize(code)
val tokensStr = tokens.json
Change in Main.scala: "This is bold" into s"This is bold $tokensStr"
Facade (a bit simplified, for full a version see GitHub):
import scala.scalajs.js
import scala.scalajs.js.annotation.JSName
#JSName("esprima")
#js.native
object Esprima extends js.Object {
def tokenize(input: String, config: js.Any = js.native, delegate: String => String = js.native): js.Array[js.Any] = js.native
def parse(input: String, config: js.Any = js.native): js.Dynamic = js.native
}
When running the html generated with fastOptJS::webpack the error is:
Uncaught TypeError: Cannot read property 'tokenize' of undefined
Inspecting the static-fastopt-bundle.js shows esprima is used, but its js is not bundled.
What other steps are needed to add dependencies into a client-only web page?
As described in this part of the documentation, you have to use #JSImport in your facade definition:
#JSImport("esprima", JSImport.Namespace)
For reference, #JSName defines a facade bound to a global name, while #JSImport defines a facade bound to a required JavaScript module.

Reusable function for database access

I am currently discovering and learning to dev an app using react native
I don't have a lot of background regarding JS/React etc (more used to C,java, objC,swift etc)
So I am converting a learning app i made in swift in RN. I used the mobile database realm. I have the habit to create a singleton classe to access some method I am using in different places.
here is how I am doing it in RN
I got a js file RealmApi like that
let realm = new Realm({
path : "Pleload.realm",
readOnly : true,
schema : [Data, SUBDATA]
});
with let say 2 methods I am exporting because I was not able to export the realm var (i did not create a class)
module.exports = {
fetchData(){..... return something}
fetchSubData(param){.... return something}
}
that I am using like this in a list view
import RealmAPI from './RealmAPI'
.....
componentWillMount(){
this.setState({
dataSource:this.state.dataSource.cloneWithRows(RealmApi.fetchSbuData(this.props.section.code)),
})
It is working, but I got the feeling it is not the good way of doing it.I am style thinking in object way (java etc)
What would be the "correct" way of doing it ? Should I create the realm in each component and duplicating the method ? (that why I am trying to avoid)
thanks
You should just be able to export realm var. The syntax is as below
let realm = new Realm({
path : "Pleload.realm",
readOnly : true,
schema : [Data, SUBDATA]
});
export default realm;
and use it as below
import MyRealm from '<file path to the above code>

Reference a class' static field of the same internal module but in a different file?

I'm using TypeScript and require.js to resolve dependencies in my files. I'm in a situation where I want to reference a static field of a class in an other file, but in the same internal module (same folder) and I am not able to access it, even if the Visual Studio pre-compiler does not show any error in my code.
I have the following situation :
Game.ts
class Game {
// ...
static width: number = 1920;
// ...
}
export = Game;
Launcher.ts
/// <reference path='lib/require.d.ts'/>
import Game = require("Game");
var width: number = Game.width;
console.log(width); // Hoping to see "1920"
And the TypeScript compiler is ok with all of this. However, I keep getting "undefined" at execution when running the compiled Launcher.ts.
It's the only reference problem I'm having in my project, so I guess the rest is configured correctly.
I hope I provided all necessary information, if you need more, please ask
Any help is appreciated, thanks !
Your code seems sound, so check the following...
You are referencing require.js in a script tag on your page, pointing at Launcher (assuming Launcher.ts is in the root directory - adjust as needed:
<script src="Scripts/require.js" data-main="Launcher"></script>
Remove the reference comment from Launcher.ts:
import Game = require("Game");
var width: number = Game.width;
console.log(width); // Hoping to see "1920"
Check that you are compiling using --module amd to ensure it generates the correct module-loading code (your JavaScript output will look like this...)
define(["require", "exports", "Game"], function (require, exports, Game) {
var width = Game.width;
console.log(width); // Hoping to see "1920"
});
If you are using Visual Studio, you can set this in Project > Properties > TypeScript Build > Module Kind (AMD)
If you are using require.js to load the (external) modules, the Game class must be exported:
export class Game {}
If you import Game in Launcher.ts like
import MyGame = require('Game')
the class can be referenced with MyGame.Game and the static variable with MyGame.Game.width
You should compile the ts files with tsc using option --module amd or the equivalent option in Visual Studio

AMD and Dojo 1.7 questions

Simple question.
Does AMD DOJO implementation support these type of declarations?
text!./plain.html
define(["../Widget","text!./plain.html"],
function(Widget,plain){
return new Widget({name:"mainApp",template:plain});
});
Load non-modules, let's say underscore.js
require(['dir/underscore.js'], function(){
_.reduce ...
});
Yes, but the precise syntax is different to that used in the question.
The Dojo Loader (1.7)
Plugins
dojo/text
The plugin for loading character data is dojo/text.
The extension should not be used when loading a JavaScript library and the location of the file is set via either a relative of the dojotoolkit base or a packages location declaration in dojoConfig:
require(['underscore'], function( _ ){
_.reduce ...
});
Configure the namespace in the Dojo configuration to avoid messy import paths - see dojoConfig in the loader documentation.
Also, consider using the dojo/global module and/or defining a Dojo module as a wrapper for Underscore.js:
//_.js
define(['dojo/global', 'underscore'], function(global){
return global._
});
With the above consideration, you must have loaded the actual .js file manually. If in conjunction with the dojo/text plugin, one would create a wrapper which also loads the required JS and evaluates it, following could do the trick.
/var/www/dojo-release-1.7/ext_lib/_.js - this sample file is hierachially placed in a library namespace, alongside dojo, dijit, dojox
define(['dojo/global', 'dojo/text!./Underscore.js'], function(global, scriptContents){
global.eval(scriptContents);
return global._ // '_' is the evaluated reference from window['_']
/**
* Alternatively, wrap even further to maintain a closure scope thus hiding _ from global
* - so adapt global.eval to simply eval
* - remove above return statement
* - return a dojo declared module with a getInstance simple method
*/
function get_ () { return _ };
var __Underscore = declare('ext_lib._', [/*mixins - none*/], {
getInstance: get_
});
// practical 'static' reference too, callable by 'ext_lib.getInstance' without creating a 'new ext_lib._'
__Underscore.getInstance = get_;
return __Underscore;
});
A sample of defining own modules using declare here
Note: this code is untested; feel free to add corrections.