How to Structure a TypeScript Project like in Java with Modules and Dependencies? - node.js

i have a problem with TypeScript and how to separate modules and import them.
In Java with Maven or Gradle, i can have three modules or projects where:
project-dao: Data Access Object classes
project-dto: Data Transfer Object classes
project-services: Services classes
project-dto is transversal to dao and services, so i can include this module like a project dependency easily in both.
In TypeScript i don't know how do make the same. I see examples with imports of compiled code in Javascript with relative paths or using npm publish for later install in another project.
Someone can i help me with some approach for this issue.
Thanks.

#Paolo : I hope your question is about creating different modules and importing them to your root module. If that's the case, you can very well create a new module with #NgModule annotation. if you want to load this module with the root module, just import this in you app.module.ts as
import {customModule} from './custom.module';
If you just want to load it lazily, include this your routing, with loadChildren property.
But, if a class that's already declared in another module, whether an app module, #NgModule, or third-party module, do not add this to the declaration.
From a DTO's perspective, I guess, you need to create an incline object as
var userObject = {
email : req.body.email,
password: req.body.password
}.
UserObject can then be passed to the next layer.

Related

Create a common/shared microservice in nestjs

How can i create a microservice that contains all the shared/common login/classes between projects?
I have a gateway, and different microservices, let say auth and account.
How can I share the user.model for example, considering that both services will use that entity?
Also considering that some common methods can be located in this common microservices in order to not have the code duplicated.
Check out the library module of microservice in Nestjs
https://docs.nestjs.com/cli/libraries
Here you can create a library module with the command
nest g library my-library
Then in that module, you can put the shared module like constant, util, etc which are common in all microservices.
To use that module import like this
import { MyLibraryModule } from '#app/my-library';

Webpack with Next.js bundles file it is not supposed to in client bundle

I have a Next.js app with mongoose to connect to my mongodb. The models import db.ts to make sure that there is an active connection to the database like so:
import { model, models, Schema } from "mongoose";
import "../../db";
This is the code that connects to my database:
import mongoose from "mongoose";
mongoose.connect("mongodb://admin:admin#localhost:27022/admin");
I have gone ahead and made some serverless functions in next.js and added some database fetching from the models in my getServerSideProps. All of which worked perfectly fine. I can interact with the models, create new Documents, delete them and update them. there are no issues.
The Problem
I recently added a new component: it is at /pages/flashcards/[id].tsx. Just like my other components, this one imports one of my mongoose models. However, for some reason, Webpack feels like it should bundle the model and its import of ../../db and send it and send it over to the client, which results in this error:
TypeError: mongoose__WEBPACK_IMPORTED_MODULE_0___default(...).connect
is not a function
Again: This does not happen with any of my other components which use the exact same models as the component which is having these problems.
The issue occurs because you have the following unused import in the /pages/flashcards/[id] page.
import question from "../../db/models/question";
Any code inside getServerSideProps or getStaticProps, and imports used exclusively by these methods, is removed by Next.js when building the client bundle.
However, since question is not explicitly being used in getServerSideProps, Next.js can't figure out the import is only meant to be used on the server. This means it will be included in both the server and client bundles.
You can use the Next.js Code Elimination tool to verify what Next.js eliminates from the client-side bundle. You'll see that if you run your page's code through it, the import is not removed. However, as soon as you reference and use it inside getServerSideProps, Next.js automatically eliminates it from the imports.
Make sure to always comment out/remove unused imports (there are linting rules to help you do that).
Have you tried upgrading the next npm package to the latest version? (12.0.8 as of this writing). I had a similar issue with Next giving inconsistent errors between different API routes, all configured the same way but some raising the same TypeError you shared. Upgrading the package resolved the issue for me.

How to use NESTJS modules in separate classes

Sometimes I need to use some methods which implemented in nestjs code structure in separate from this classes
For example we have such architecture:
entities
-entity.entity.ts
-entity.module.ts
-entity.service.ts
-entity.providers.ts
So how Can I use method or property from entity.service in separate class? Such like this:
import EntityService from './entities.entity.service'
export class SeparateClass{
propertyFromEntityService: string
constructor() {
this.propertyFromEntityService = EntityService.propertyFromEntityService
}
}
And one more important point. I don’t want to implement this separate class in the nestjs structure, I just want to use it as a regular class. Thank you
If you are not wanting to use dependency injection via Nest, but you still want to use a property from a class in the Nest application, you'll need to manually instantiate the class, providing whatever dependencies that class has, and then pulling the property from the service. The other option, if this class will be used outside of the Nest context, but still while the Nest application is running, is you can use the Nest application to get the service via app.get(EntityService), but this does require you to have access to app after the NestFactory has created the application.

How do I mix Typescript namespaces with External modules when "Don't do it" is not an option

Situation
I have a Typescript app written using namespaces. I want to move some of this logic (Google OAuth) out of the client and into a node service. I have created a nearly complete project for that here.
This new project has a node component that will make authorisation requests to google using a secret key and a client component that can be re-used by other applications that will communicate with the server. I also have a testHarness app that uses this client to test it and make sure that I can use it in a namespace based application.
I have some shared interfaces that both the client and server consume.
I want my client code to be usable in projects that use externam modules and namespaces - i.e. my existing project.
It must be possible
I have read in many places
Do not use "namespaces" in external modules.
Don't do this.
Seriously. Stop.
Such as on this answer but I am still convinced that this must be possible. The reason that I think this is that in my project I have a dependency on RxJs. This project in my node_modules folder is used by both the client and the server.
What I have tried
In my project I have a contracts.d.ts file that I want to share between both the client and the server.
StackOverflow
I looked at this question:
Typescript es6 import module "File is not a module error"
And made my contracts look like this:
// test.js - exporting es6
export module App {
export class SomeClass {
getName(): string {
return 'name';
}
}
export class OtherClass {
getName(): string {
return 'name';
}
}
}
and then tried the various import methods listed:
import * as app1 from "./test";
import app2 = require("./test");
import {App} from "./test";
I got each of these to work so that my server AND client compiled correctly but then as soon as I tried to compile my testHarness app - that uses namespaces - it failed:
src/testHarness/testHarness.ts(4,38): error TS2304: Cannot find name 'PricklyThistle'.
src/testHarness/testHarness.ts(4,38): error TS2503: Cannot find namespace 'PricklyThistle'.
Copying Declaration Files from node_modules
As I said, I am convinced that this is possible as dependencies that I import into node_modules are used by both my client and server projects and my client can still be used with internal namespaces.
To go down this route I edited a d.ts file in the Rx ts folder and added a new interface. I verified that both client and server could use this interface and that my testHarness app (with namespaces) woudl compile. All was good!
I then copied this edited file into my common folder. I had to rename the module to avoid conflicts but then I get:
src/node/youTubeAuthenticationServer.ts(3,23): error TS2306: File '/src/common/rx.test.d.ts' is not a module.
My edited declaration file looks like:
declare module RxTest {
export interface TestInterface{
propertyOne: string;
propertyTwo: number;
}
}
declare module "rx.test" { export = RxTest; }
Workaround
For now I have just copied the interfaces that are used by both applications. This works and there are only 2 small interfaces so it's not a big deal. It is very anooying though. One of the great things about node is that is uses the same language as the browser. If you can't share code that is not good. I also have other much larger code bases that I want to do similar things with and in these situations copying code will not be a viable solution.
Any new projects I work on I will exlusively use external modules but when working with legacy code this is not always possible.
I really hope someone can help.
Thanks
If find your question a bit confusing, there's too much description and too little examples (code/configuration) of what you have.
Try to do this:
declare module "rx.test" {
export interface TestInterface{
propertyOne: string;
propertyTwo: number;
}
}
If that doesn't work, please edit your question and add the directory structure that you have, the tsconfig.json file(s) that you have, explain how you build (tsc, gulp, etc) and so on.

Sharing TypeScript classes between client and server

I have a Node.js project written in TypeScript. In my project, I have a folder named "public" which contains the client side code & HTML and also a file named classes.ts which is supposed to be shared to the server side.
The problem is that I need to add "export" before the classes declaration in order to make them accessible in the server, but then in the browser I get this Error:
Uncaught ReferenceError: exports is not defined
I found these questions:
https://github.com/Microsoft/TypeScript/issues/5094,
Setup a Typescript project with classes shared between client and server apps?,
Share module between client and server with TypeScript,
which suggests using commonjs in the server but amd in the client. The problem with this solution is that they have 3 different projects (server, client and shared) whereas I only have one project in which I use commonjs.
Another suggestion is:
the other option, which is more convoluted and will require a post
build step to massage the code; if you can not use module loaders in
your client code, is to isolate all module dependencies in your server
code, then in the shared, they are just classes. Build the shared
files without --module, and no exports or imports, but all inside a
single namespace, say namespace MyApp { ... }; in your client code,
you include them directly, and emit using --out. in your server code,
you first emit the shared code to a single file, shared.js, and a
single .d.ts shared.d.ts, augment these with some code to export them
as a module, e.g. append exports = MyApp at the end of your shared.js
and shared.d.ts, then import them from your server code.
But I don't want to deal with updating .d.ts files all the time, and I'm also not sure it will work in one project.
Any suggestion how to make a TypeScript class accessible both in browser and server?
Any help will be profoundly appreciated!
This is absolutely possible.
I have a project containing both SPA client application that runs in browser and server running in node.js that both share common typescript classes. For all of this I have just one tsconfig.json file (I am still not sure that this is the best approach but for now it works just fine)
Here are parts of my setup:
Use modules (previously called external modules). No need for namespaces and d.ts files for your own modules.
module = "commonjs" in tsconfig.
On client side use System.js as module loader (this will solve your 'Uncaught ReferenceError: exports is not defined'). You can use angular2 5 min quickstart as reference how to setup system.js.
It works like a charm.

Resources