import an extension module in node - node.js

I have a Node.js Angular app which I am trying to import babylon.js into.
Current Setup
1) npm install --save babylonjs to get the npm repo installed in my project's node modules.
The following image depicts the folder structure of the npm repo.
2)In my angular component I import the BABYLON declaration from the babylon.module.d.ts and babylon.max.js files in the above picture like so.
import * as BABYLON from 'babylon.js'
Babylonjs now works great, has typings enabled and everything, so I
can use BABYLON as pictured below
Problem
None of the included extensions are hooked up. These extensions are located in the following folders
(Full folder structure is in the first image. I left the gui folder open since that is the specific extension I am >trying to activate at this time)
The main babylon.module.d.ts file defines BABYLON as follows:
declare module BABYLON { //class types are defined in here }
The gui extension (all others follow the same logic) declares itself as a part of BABYLON as follows:
declare module BABYLON.GUI { //extend classes & create new classes in here in here }
Attempted solutions
1) babylon.gui.d.ts declares BABYLON.GUI so I simply tried the following
import * as BABYLON from 'babylonjs';
import * as BABYLON.GUI from 'babylonjs/dist/preview release/gui/babylon.gui';
This generates the following Typescript error: Duplicate identifier 'BABYLON', which is not surprising, however, BABYLON.GUI is how thebabylon.gui.d.ts` file declares its parts.
2) Using the CDN in the index.html file. This works, however, types will not work. Even if I got typings to work,using the CDN is less performant. The resources will be loaded in the document <head> every page. with imports the resources will only be queried when the component is active.
3) Appending the babylon.gui.d.ts file to the babylon.module.d.ts file. BABYLON.GUI` is still undefined.
Modifications to the npm repo are undesireable anyways, since any npm updates, or installs will overwrite the changes.
4) I spoke with a BABYLON developer here, and we kind of hit a dead end.
Does anyone have any input on how to import this extension properly?
PS. once we get this answered I'm going to work with the dev to implement a seamless experience for all node users who wish to incorporate babylon.js into their projects!

I spoke with the lead developer deltakosh about this.
To clear a few things up:
This issue is not with npm
This issue is not with node
This issue is with how Babylon is structured
The developers are actively refactoring to support the import behavior desired in the above question.
If anyone is curious here is the link to the open issue on github pertaining to this question.
In the interim to use Babylon while import support for importing packages is being worked on I have done the following:
Use the CDN for all babylon libraries
To get rid of typescript compilation issues declare the following at the top of your .ts file declare let BABYLON: any; This will make babylon with packages useable, however, we will not have any typings benefits in the interim.
Feel free to chime in if you have found a more elegant interim solution!

Related

Node/NPM How to map import paths

I have an NPM module that uses another local NPM module containing shared code. Neither of them are public, this is all local.
I import the shared module in my package.json like so:
"my-shared": "file:../my-shared-code"
When I npm install, my-shared-code gets imported correctly, and I can import code like:
import Blah from 'my-shared/src/sharedTypes';
Problem
I have to use the word "src" in the import. However, when I build I create a build directory, which breaks all these imports!
I was wondering if I could use NPM to map the imports somehow?
Can I make it so I don't have to use the word "src" at all?
Could I just do:
import Blah from 'my-shared/sharedTypes';
and then it magically figures out whether to use the "src" or "build" dirs?
What I tried
I looked into the options for package.json, and there is a "files" property that I thought might help. However I think that just whitelists files.
I also looked into the "main" property, however I'm not "exporting a module". I just have a load of utility files that I wanna be able to import into multiple other projects.
What I'm actually trying to achieve
I'm using typescript, and I've got a front-end and a backend that both share types for certain models, but also share some utility functions.
I want my typescript/react front-end and my typescript backend to be able to import typescript files from another node_package, however it needs to know to use "src" for development and "build" when built for production.
While it's not exactly what you're asking for, you might be looking for npm link. It's not intuitive, but it's what I use for your above situation.
npm-link is a way of registering local projects so that others can reference them. Just beware that reading the docs is important -- using it may impact your local environment in non-obvious ways (especially if you build and publish directly from your machine--versus CI/CD).
In the consumer project you can use path mapping --> https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping
As for the package, you can re-export using export * from './my-file' syntax, in a index.ts file (you may need one at each directory). But this is tedious if you have a lot of files. (imperfect example)
Another solution seems to make a script to copy the package.json into the dist folder and make the build there.
There is a similar discussion there: How to npm publish specific folder but as package root

Shared library from Create React App projects giving (jsx isn't currently enabled error)

I'm attempting to use a shared library for reusable components and using just 2 out of the box Create react apps. One is called 'shared-lib' the other 'project-example'. I made a super simple component in shared-lib, exported (working when I test). I NPM linked both seemingly correctly (shared-lib is in my project-example node_modules with a special icon).
I built the shared-lib, I also imported the shared component (SharedComponent)
import SharedComponent from 'shared-lib'; <- lib is in my node_modules
../shared-lib/src/index.js
SyntaxError: /Users/bemker/dev/portals-modern/shared-lib/src/index.js: Support for the experimental syntax 'jsx' isn't currently enabled (8:3):
Add #babel/plugin-transform-react-jsx (https://git.io/vb4yd) to the 'plugins' section of your Babel config to enable transformation.
I'm following a vid tutorial and he didn't have to eject his create react app, but I'm guessing this is where the error is coming from.
Here is the vid I'm following if anyone wants to take a look. https://www.youtube.com/watch?v=B7iYJT_ll-U
Anyone know why this is occurring, or how to get past it (preferably without ejecting)?
I couldn't find a solution using the above, but there is a package similar to Create React App for building libraries that made it pretty easy. Its not maintained by FB, but it worked for me.
https://github.com/transitive-bullshit/create-react-library
https://github.com/transitive-bullshit/react-modern-library-boilerplate (multiple exports)
vid tutorial using it: https://www.youtube.com/watch?v=N8d-CLmg3hw
second w/ 'real' usage: https://www.youtube.com/watch?v=6R699AQYH74
Hope this helps someone.

Tutorial for creating custom typescript libraries

I am a relative newbie to node.js and typescript and am looking for tutorials and examples for building custom libraries for typescript. I am currently working on a project(switched to WebStorm GUI) that requires I build several microservices and several of the microservices will need to share certain code, i.e., base repository functionality, etc. My though would be to move the code they have in common to a series of separate libraries(projects) and make them into typings and have the projects that need them to install them. Following the example I found here, and using grunt: What is the story for creating and consuming TypeScript libraries?, I was able to generate the .js file and the .d.ts files in a dist folder on the project. There are a few areas that I am confused about:
1) The example makes reference to a "main": "./dist/my.service.js" section in the jsconfig file, how necessary is this file and what should go into it?
2) If all of the files are transpiled and added to the dist folder, will the dependent code still be able to access it or do I have to transpile all of the files to root?
3) After I have have all of the file successfully transpiled and moved to the proper location, how do I install them to the dependent project if they are local and not up on the npm or Definitely Typed, etc.?
Well if you would like to see an example project that I am currently working on that at the moment can be installed with npm is binary-type-tree. There are some things I need to fix but overall the project is working great. You can see my setup for Jest in my package.json. Along with how to set up the types and the main.
Depending on what your library will be focused on you will want to choose the appropriate module system. Right now commonJS is the most common for npm packages. Although you can only compile to one file with system or amd.
As for compiling you do not need gulp/grunt you can use Webstorms IDE to compile your files. Simply open up the Webstorm settings "Languages and Frameworks" and select "Typescript" there you will see enable Typescript compiler.
The example given is very old. Typescript had a major update to how typings work back in October of 2016, they moved to Typescript 2 I think, or maybe it was November. Anyway when you google search Typescript I would set the filter to not before that time.
1.
The main in the package.json of the Typescript project should point to the entry point of your library, or your executable. Since mine is a library it points to the compiled folder's index file. The file does not exist in my repo but it is there upon compilation.
2.
This I believe is answered depending on your build. In my build as an example I use module system es6 as you can see in my tsconfig.json file. This uses the ES6 module system.
if you would like to use commonjs the structure of my project will still work properly except you will need something like Systemjs or Babel on the front end.
3.
This one is a bit unknown to me but what I have done for only testing is copy my directory into the node modules of another project I am working on. Now to require the project you do not need a #types since I have "declaration": true in my tsconfig.json file. The package.json of my project has a "types": section which points to the compiled .d.ts file. The project that is requiring this new TS package, if also written in TS, will have to have the typeRoots and types section in the tsconfig.json file. Once this is all set up you should be able to require it just fine.
Make sure that the src of all your TS files is declared in the includes section of the tsconfig if your files are not compiled to root. Otherwise your project will have to require in files in an odd format like import * as BTT from "lib/basic-node/avl-tree";. Which is not what I wanted, once I added this it became import * as BTT from 'binary-type-tree';.
The "main" field in your package.json tells Node's module system what file to require when calling require(), so you will definitely need it. You point that field to a transpiled file, which will also contained transpiled references to your other transpiled TypeScript files, so you shouldn't have to add anything to root.
If you're trying to use the package from another project, you simply reference it as a dependency using NPM the same way you would with any other JS project.
{
"name": "dependent-project",
"dependencies": {
"bar": "file:../typescript-project"
}
}
Again, Node will know how to load the TypeScript project because you've specified the transpiled entry point in the main field.
There are several things you must consider:
In package.json, you must set some things up (example):
main property to point to your UMD compatible bundle
module property for ES5 module. Then modern workflows can benefit from it, for example to apply Tree Shaking
typings pointing to your .d.ts file (which should be generated)
That counts on a build process, which can be made with a module bundler, such as RollupJS or Webpack. They can generate source maps and so on.
As per question 3: you can install packages from local or even from Git repos. In your package.json, for example:
"your-library": "git+https://github.com/alexjoverm/typescript-library-starter.git"
I'd suggest you to take a look at TypeScript Library Starter. You can find there everything you need. It has configured out of the box:
Automatic releases
Package.json configuration
Universal module bundles
Source Maps
Typings (.d.ts) auto generated
Docs using TypeDoc
Tests and coverage

Typescript Custom Node Modules

I'm trying to fully understand how Typescript works in a Node.js project. To accomplish this I have created my own custom_modules folder with a separate #types folder underneath for my declarations while the actual implementation is under the custom_modules attempting to mimic the structure of node_modules. My goal is to make this module usable in the project non-relatively with separate declaration and implementation. I have been able to setup a project that compiles with this setup, but running it errors with:
Cannot find module 'foo'
The source is available here:
https://github.com/anorborg/learn-ts
The node_modules folder is a somewhat special case in how typings get handeled. This is a result of how nodejs works. Take a look at the [module-resolution] doucmentation (https://www.typescriptlang.org/docs/handbook/module-resolution.html), it describes more in depth how module resolution work in typescript.
But in short to answer your question: you can not use non-relative module paths in this way. Node will look for the file in node_modules at runtime, and will not find it there. The paths property in the tsconfig.json is there to solve problems that can occur in other cases, as when targeting RequireJS or SystemJS for example, but not when targeting node.

visual studio not finding firebase node module

I used the command npm install firebase --save from the root of my project folder and a firebase folder was successfully added to my node_modules folder and the packages.json was also updated.
I also use typescript so I have a app.ts file where I try and do import Firebase = require("firebase");
However it doesn't work. I get red squiggles and error saying cannot find external module "firebase".
I have installed express and importing it in app.ts as well and that works fine, no errors.
I have tried to look through the firebase source but its minified and impossible to try and do any finding there, about what is exported and such.
Any ideas about what might be wrong and how I can fix it?
Three things:
You should download the Firebase type definition from Definitely Typed using NuGet, TSD, or some other method.
The Firebase definition on Definitely Typed doesn't seem to be written in an external module form. You may need to add the line export = Firebase; at the bottom of it.
TypeScript currently has odd default behavior with definition files (d.ts) that describe external modules written in JavaScript; it will search in each directory from the directory where the file is back to the root of the current drive looking for a .ts or .d.ts file with a name that matches the name of the thing you've imported. So your best bet is to move the Firebase.d.ts file to the root of the project. If you're interested in a bit more discussion on this, check out https://github.com/Microsoft/TypeScript/issues/2338 . They're working on it.
If you do those three things, it should work.

Resources