New Scala.js facade for Three.js -> "Cannot find module "THREE"" - three.js

As https://github.com/antonkulaga/threejs-facade is heavily outdated I tried an approach like: https://github.com/Katrix-/threejs-facade and would like to create a facade for the new three.js library.
I am by no means a JS expert, nor am I a Scala.js expert, so odds are I am doing something really dumb.
After another question I am using this sbt-scalajs-bundler and sbt-web-scalajs-bundler
My build.sbt looks like this:
lazy val client = (project in file("modules/client"))
.enablePlugins(ScalaJSBundlerPlugin, ScalaJSWeb) // ScalaJSBundlerPlugin automatically enables ScalaJSPlugin
.settings(generalSettings: _*)
.settings(
name := "client"
//, scalaJSModuleKind := ModuleKind.CommonJSModule // ScalaJSBundlerPlugin implicitly sets moduleKind to CommonJSModule enables ScalaJSPlugin
,jsDependencies += ProvidedJS / "three.min.js"
)
lazy val server = (project in file("modules/server"))
.enablePlugins(PlayScala, WebScalaJSBundlerPlugin)
.settings(generalSettings: _*)
.settings(
name := "server"
,scalaJSProjects := Seq(client)
,pipelineStages in Assets := Seq(scalaJSPipeline)
//,pipelineStages := Seq(digest, gzip)
,compile in Compile := ((compile in Compile) dependsOn scalaJSPipeline).value
)
three.min.js is in the resources-folder of my client project.
One part of the Facade is e.g.
#js.native
#JSImport("THREE", "Scene")
class Scene extends Object3D {
and I want to use it like this: val scene = new Scene. On scala.js side this actually compiles just fine, but when I run it I get:
Error: Cannot find module "THREE"
in the browser and I wonder why. It's called like this in three.min.js after all.
Now I tried providing and serving the three.min.js file from the server side as well, because I thought that maybe it was just missing at runtime, but no, that does not seem to be the cause.
So now I wonder what am I doing wrong here?
Just to clarify: Rest of transpiled js works just fine, if I do not export any usage of the Facade!

As explained in this part of Scala.js documentation, #JSImport is interpreted by the compiler as a JavaScript module import.
When you use the CommonJSModule module kind (which is the case when you enable the ScalaJSBundlerPlugin), this import is translated into the following CommonJS import:
var Scene = require("THREE").Scene;
This annotation only tells how your Scala code will be interfaced with the JS world, but it tells nothing about how to resolve the dependency that provides the THREE module.
With scalajs-bundler you can define how to resolve JS dependencies from the NPM registry by adding the following setting to your client project:
npmDependencies += "three" -> "0.84.0"
(And note that you can’t use jsDependencies to resolve these modules with #JSImport)
Also, note that the correct CommonJS import to use three.js is "three" instead of "THREE", so your #JSImport annotation should look like the following:
#JSImport("three", "Scene")
Alternatively, if you don’t want to resolve your dependencies from the NPM registry, you can supply your CommonJS module as a resource file. Just put it under the src/main/resources/Scene.js and refer to it in the #JSImport as follows:
#JSImport("./Scene", "Scene")
You can see a working example here.

Related

Go type cast fails despite the type being the same

I am using the jackc/pgx driver alongside the GORM library to interface with a PostgreSQL database.
I have an instance where I have to check the PostgreSQL error code and handle a certain error type differently. When using the pgx driver, the GORM methods return a *pgconn.PgError type as the error, which contains a field with the specific error code.
In order to access that field, I must cast the error to a *pgconn.PgError, but for some reason this is failing:
res := tx.Take(&f, "id = ?", id)
if res.Error != nil {
if pqErr, ok := res.Error.(*pgconn.PgError); ok {
// does not reach here
} else {
fmt.Printf("Error type: %T\n", res.Error)
// Output: "Error type: *pgconn.PgError"
}
}
Notes:
The pgx and pgconn packages are inside the same project, so it's not the case that they are returning different versions of a type with the same name. In other words, I only have one import in my go.mod.
The returned value is not nil.
A debugger reveals that the type is a *pgconn.PgError.
You've solved your own issue, but here's some perhaps helpful background, and how I found the source.
Packages of the same name can exist in the same program, so long as they have different import paths. For example, the standard library has both math/rand and crypto/rand, each called rand. This is the first hint of how *pgconn.PgError and *pgconn.PgError are not the same: they come from different import paths.
When modules in Go make major revisions, they are supposed to change their import path. This is to preserve backwards compatibility with respect to import paths. Note that this is usually done by updating the module declaration in the go.mod file, rather than actually moving the code into a sub-directory. For example, see this commit where pgx was bumped from v4 to v5. This is the second hint: code from the pgx project is available under multiple import paths (due to the multiple major versions).
With this background in mind, I used the git tags to view the repository at the latest v4.x.x release. I noticed that oddly, the pgconn package did not exist in v4. This seemed to rule out the idea of a github.com/jackc/pgx/v4/pgconn vs github.com/jackc/pgx/v5/pgconn conflict. I then Google searched for "pgconn" and found the github.com/jackc/pgconn repository, where I saw in the README:
This version is used with pgx v4. In pgx v5 it is part of the https://github.com/jackc/pgx repository.
From the other information you've given, your mistake may have been using the import path "github.com/jackc/pgx/pgconn". As shown in the example code for pgx, the current import path you should be using for the base module is "github.com/jackc/pgx/v5", and packages within it would be specified similarly, e.g., "github.com/jackc/pgx/v5/pgconn".
As #HymnsForDisco correctly pointed out in the comments, both github.com/jackc/pgconn and github.com/jackc/pgx/pgconn exist. It turns out that the returned error was from the former, whereas I was importing the latter in my code.
To confirm, I added the following line:
fmt.Println("Error path: ", reflect.TypeOf(res.Error).Elem().PkgPath())
// Output: "Error path: github.com/jackc/pgconn"
Changing my import to "github.com/jackc/pgconn" resolved the issue.

Typescript Type definition for d3 sankey

I have some javascript code which uses d3 sankey plugin for creating a chart. In my new project, I need to reuse the same code, but the new project is in typescript. I am looking for a DefinitelyTyped file for the plugin. I browsed through https://github.com/DefinitelyTyped/DefinitelyTyped, but couldn't find it.
Is there any other location where I can get this file from?
Sankey plugin link: https://github.com/d3/d3-sankey
Also, without a d.ts file for this plugin, is there a way to access it through typescript?
The code in d3 plugin looks something like this:
d3.sankey = function () {
// Rest of the code goes here
}
The way I use it in javascript is as below:
d3.sankey().nodeWidth(30).size([100,100]);
Would appreciate any help or guidance.
Thanks!
As a heads-up, I have just submitted a Pull Request #16051 to DefinitelyTyped which contains TS definitions for d3-sankey.
Once they are merged, they will be published as per standard process to npm/#types. I.e. npm install --save-dev #types/d3-sankey will do.
IMPORTANT: When I wrote them up, I noticed that the current API documentation in the d3-sankey repo appears to be in some need of rectification (e.g. missing methods, mentioning of accessor functions, which are not used in the code base)
When I have a second, I will file an issue there/submit a PR.
UPDATE (2017-05-01):
The "official" TypeScript definitions for d3-sankey are now available (see npm #types/d3-sankey). Simply use them with npm as indicated above.
The PR to update the actual API documentation of d3-sankey to reflect the source code is still awaiting a merge here.
You need to expand the definition of the d3 type to include the sankey() method and the methods it accepts.
At the absolute minimum, you need to extend the d3 module with a declaration file to make clear that d3 has been extended with the d3-sankey module. You do so by creating a definition file that you place within the #types directly with the following contents:
declare module 'd3' {
export function sankey(...args[]) : any;
}
This tells TS that there is a d3 module, and that it exports the function listed. If the d3 module already exists, it extends that module.
So you can then import the d3 service and use it:
import dd3 = require('d3');
dd3.sankey();
If you want to expand on the type file, you instead write the definition file as so:
declare module 'd3' {
interface ISankey {
nodeWidth() : number;
nodeWidth(width : number|{(arg: number) : number}) : void;
// Add Other d3.sankey Methods Here
}
export function sankey() : ISankey;
}

Elm find unused functions

Let us for example have app like this:
port module MyApp exposing (main)
import Html.App as App
main =
App.programWithFlags
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
Could we safely assume that only useful functions are the ones that are ports and anything that is called from init, view, update or subscriptions?
Because after some refactoring I stopped calling some function. Is any compiler flag or linter that could notify me that function could be safely removed?
You can only detect unused module imports while running elm-make with --warn flag.
That's all you could get from the compiler today.
Just remove stuff and compiler will tell you, if you have to put it back, I guess.

Using an External Dependency in a Library

I am using wgo for dependency management in Golang (although I think wgo has little to do with this), wgo has a folder structure like this
project/
.gocfg/
gopaths
vendor.json
vendor/
src/
github.com_or_whatever/
I have a library I coded myself which uses an nsq-go type in one of the exported methods:
func AddNsqSubscription(
topic, channel string,
handler nsq.Handler,
config *nsq.Config) error { }
The library is called messi and I import the nsq-go like so "messi/vendor/src/github.com/bitly/go-nsq"
The problem comes when I try to use this library in another project. For instance, in a project called scribe I have the following code (notice the imports):
import (
"scribe/vendor/src/github.com/bitly/go-nsq"
"scribe/vendor/src/messi"
)
//...
nsqHandler := nsq.HandlerFunc(func(message *nsq.Message) error {
msgHandler(MessiMessage{message})
return nil
})
return messi.AddNsqSubscription(destination, subdestination, nsqHandler, nsq.NewConfig())
When I go build the following error is returned:
cannot use nsqHandler (type "scribe/vendor/src/github.com/bitly/go-nsq".HandlerFunc) as type "messi/vendor/src/github.com/bitly/go-nsq".Handler in argument to messi.AddNsqSubscription:
"scribe/vendor/src/github.com/bitly/go-nsq".HandlerFunc does not implement "messi/vendor/src/github.com/bitly/go-nsq".Handler (wrong type for HandleMessage method)
have HandleMessage("scribe/vendor/src/github.com/bitly/go-nsq".Message) error
want HandleMessage("messi/vendor/src/github.com/bitly/go-nsq".Message) error
Why? I do not really know what is going on. The code go-nsq imported is exactly the same, yet golang wants that this code comes from the same folder?
What am I doing wrong?
Packages in Go are identified by full import path, not by name.
For example in the standard library there are two different packages with the same name template but different import paths: text/template and html/template.
You should make sure that go-nsq package is imported using the same path.

Cache won't work in Appcelerator

Titanium SDK version: 1.6.
iPhone SDK version: 4.2
I am trying out the cache snippet found on the Appcelerator forum but I get an error: [ERROR] Script Error = Can't find variable: utils at cache.js (line 9).
I put this one (http://pastie.org/1541768) in a file called cache.js and implemented the code from this one (http://pastie.org/pastes/1541787) in the calling script, but I get the error.
What is wrong? I copied the code exactly.
Your problems is whilst the first pastie defines utils.httpcache. The variable utils is not defined outside of this function closure (because it is not defined anywhere in global namespace). As below shows.
(function() {
utils.httpcache = {
};
})();
To make it all work in this instance add the following code to the top of your cache.js file.
var utils = {};
This declares the utils variable in global namespace. Then when the function closure is executed below it will add utils.httpcache to the utils object.
The problem is actually not specific to Appcelerator and is just a simple JavaScript bug. Checkout Douglas Crockfords book, JavaScript the Good Parts. Reading it will literally make you a more awesome JavaScript developer.
You can't use utils.httpcache.getFromCache(url) until you add this to your code:
var utils = {};
That's because how the author created his function, it's called JavaScript module pattern and it's generally used to structure the code.
I seem to lose this value "value.httpCacheExpire = expireTime;" when the code does the "Titanium.App.Properties.setString(key,JSON.stringify(value));" so when I get it back using the getString method, there's no longer the "value.httpCacheExpire.
Anyone else have this issue? Am I missing something to get this working?

Resources