TypeORM Share Entities Across Web and Node - node.js

I am using Webpack 4.7.0 to compile two entypoints - a server (node) and client (React), all in Typescript using ts-loader. I have a set of entity classes I would like them to share, however they are all written to be used by TypeORM (with #Entity decorators), thus requiring an import x from "typeorm".
This, of course, does not play nice when compiling the client bundle, as typeORM depends on many NodeJS libraries. I have tried adding externals: ["typeorm"] to my client entrypoint, but I then get a ReferenceError: "typeorm" not found in my browser.
Is there any way to share TypeORM entities across platforms?

Related

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.

Jest, NestJS, TypeORM End To End Testing

In the NestJS tutorial E2E tests are set up with their single example module imported.
This pattern does not seem to work in an application with more complex relations between the typeORM entities. After extensively checking that there were no inconsistencies in import statements and no missing TypeOrmModule.forFeature() in the relevant files, I gave up and simply imported my entire AppModule (root module for my application -- same as NestJS default).
In short if you are seeing of the form
Error: Entity metadata for EntityA#entityB was not found.
Check if you specified a correct entity object and if it's connected in the connection options.
You can try importing all the related modules or simply import your entire application.

How to avoid multiple copies of react when both module and project are bundled with webpack 2

I have made a module named as services which serves the loading bar, notifications and flash banner etc to other projects. I bundled this module by babel and it was running perfect but as the requirements kept growing for services so i have to bundled this from webpack-2 because of css type issues. I bundled it as a library. But when i uses notifications which are imported from services, it gives such warnings
Uncaught Error: addComponentAsRefTo(...): Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component's `render` method, or you have multiple copies of React loaded
and
index.js:25 Uncaught TypeError: Cannot read property 'componentWillEnter' of undefined
PS: I have already tried resolve.alias and externals properties of webpack but no use :( Any suggestions Please?

what is the proper way to create a swagger web service in TypeScript

I am part of a project written in TypeScipt and I am trying to add TypeScript Web Server which will be compatible with Swagger.
What is the most basic strategy to implement it, considering easy maintainability.
For Typescript I have notice that exists 'Typson' library for generating a JSON Model from TypeScript Interface.
For Swagger, I have tried using 'swagger-node-restify' library, since it supports adding JSON models to swagger.
However, I encounter some problems:
Typson doesn't support typeScript syntax of Import -
(import {Server} from "restify")
I tried to implement the 'swagger-node-restify' example (Pet Example), however the RESPONSE of the localhost:8080/api-docs.json GET Request is missing all the SPEC data of the API.
{"apiVersion":"0.1","swaggerVersion":"1.1","basePath":"http://localhost:8080","apis":[{"path":"/api-docs.{format}/pet","description":"none"}]}
I suggest to describe a Swagger compliant API using yaml or json and to generate the server from that.
swagger-server can build APIs on top of express in real time (no source code generation).
There are JavaScript code generators :
Call the swagger-codegen client with -l nodejs-server
swagger-node is a great alternative but seems hard to integrate with TypeScript
Yes, you can easily generate Swagger and OpenAPI documents from your TypeScript types by using tsoa. The readme contains all of the setup information that you would need to start using it. It's compatible with express, hapi, koa, and more (via the ability to add your own template for your preferred server type):
https://github.com/lukeautry/tsoa
The advantages that tsoa has over other libraries is:
it both generates the swagger/OpenAPI document and it also validates the types at runtime
(Full Transparency: I am one of the maintainers of tsoa. But I was first a consumer of tsoa and I find it to be a great product... that's why I asked to help maintain it! :) )

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