I'm trying to figure out the best way to write a class library in Typescript and deploy it to NPM with a definitions file.
The classes in the library are essentially models that are shared across our various RESTful services. Some of them have a few utility functions.
In my current process, I've created a single module where all of the classes can be accessed from (index.js). And then I manually maintain a .d.ts that has all of the class and interface definitions. Any time I make a change to the actual implementation, I must remember to also update the definition file.
When I deploy to our private NPM server, I only deploy the the transpiled .js files and the definitions file. Services that install my npm package just need to add a single /// <reference path="..." /> to their references file.
This works; it's just cumbersome and error-prone. Is there a decent/easy way for me to generate a single definitions file automatically from all of the classes I have? If not, is there something different I can/should do to share common Typescript modules across projects?
All you have to do is add --declaration to your compiler options and it will create the corresponding d.ts file/s for you. No need to do that manually.
Related
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
I have a concept of a nodejs server service, that consists of
a rest API and
some asynchronous workers.
Both should live in different subnets and git repositories. But both access database and should use the same entities and types.
So I would like to have something like shared module (don't know the proper term in npm ecosystem) with just entities / types, that would use typescript and use that shared module in both rest API and async workers. The shared module needs to be versioned in git separate (private) repository.
How can I do this in nodejs?
So far I read something about treating it like a library (here and here). I especially don't know, how and where should I put the js files, compiled from typescript.
If all you need is versioning, maybe consider treating it like a regular npm module?
npm-install supports git repositories and git supports release tags release tags
From those two all you need to do is compile typescript to an index.js file at the root of the module (library), and you can access it by require inside where it's needed.
(just be mindful that you will need each shared repository to have a package.json)
I'm trying to write a universal React.js application using TypeScript and if possible it would like to somehow annotate certain TypeScript files in such a way that a file is understood to be running inside a browser context or Node.js context explicitly. So that any attempt to use browser APIs from within Node.js environment would fail, and vice versa. How can I do that?
Right now the files reside in the same directory and maybe that the problem because I cannot have multiple tsconfig files but if that is the only solution I guess I have to do it that way.
Each project described by a tsconfig.json file has a single set of visible declarations; there's no way to have different declarations visible in different files in the same project. You can put a <reference> directive in a specific file, but the directive will affect the entire project. So to enforce what you want using the regular type checker, you'll need to use multiple tsconfig.json files. There may be other approaches such as using the tslint "ban" rule to ban all APIs from one environment in a specific file, but I doubt they will be practical.
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
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.