Comments (23)
Well, I was thinking that I may not be the only developer who wants to easily use the Entities as DTOs while coding let's say a REST API. I'm still struggling to see a nice and clean way to do so.
But you're right, it's not directly linked to TypeORM. Sorry to spam this thread and thanks for your work.
from typeorm.
Sorry to come back to this, but the actual solution may not cover one use case.
Usually I'm using TypeScript interfaces, in a separate repository, for both my client and my server. This allows for easier manipulations: my client and server knows what they are going to receive, interfaces updates are shared to both repo, etc.
I'm using Nest.js and Typeorm together (and it's working quite well), but I'm struggling to find a good solution. Nest.js routes expects classes as DTOs, and while I could use the entities this lead to non-logical behavior (fields may be set, but all the methods are undefined).
public async updateUser( @Param() params, @Body() user: User) {
user.id = params.id;
user = await this.userService.update(user);
if (user == null) {
throw new HttpException('Not Found', 404);
}
return user;
}
So I'm thinking about generating (via gulp or webpack) DTOs based on the entities, to clarify the separation bewteen DTOs (data) and Entities (objects with methods). I'm not quite sure that the previously mentioned shims can do this, as I'm not well versed into webpack.
For example this file :
import { Entity, Column, PrimaryGeneratedColumn, BaseEntity, OneToMany } from 'typeorm';
import { Project } from 'entities';
@Entity()
export class User extends BaseEntity {
@PrimaryGeneratedColumn('uuid')
public id: string;
@Column()
public firstName: string;
@Column()
public lastName: string;
@Column()
public email: string;
@Column()
public password: string;
@Column()
public admin: boolean;
@OneToMany(type => Project, project => project.user, {
cascade: true,
})
public projects: Project[];
}
Would become
import { ProjectDTO } from 'dtos';
export class UserDTO {
public id: string;
public firstName: string;
public lastName: string;
public email: string;
public password: string;
public admin: boolean;
public projects: ProjectDTO[];
}
It's not trivial, but maintaining 2 copies of the same file is also pretty cumbersome.
from typeorm.
I ran into this issue too in react native. Even though its debatable whether or not it's advisable to share models between the repository, server, and client, I think that concept is one of the best parts about typeorm. Is there any progress on making it modular? For now are the decorators from ionic-orm compatible with typeorm?
from typeorm.
I advised against combining the frontend and backend systems for quite awhile. There were too many advantages to typescripting everything together to not at least try. So far it's been working out great.
from typeorm.
I too experienced this issue. Had to have my BE classes subclass my FE classes in the meantime.
from typeorm.
since i webpack the FE and grunt together the BE I created a typeorm-fake.ts file with all the decorators returning empty functions. in webpack.config.js i told resolve.alias: { 'typeorm': './typeorm-fake' }
been working so far, I also do not have super complex data structures.
typeorm-fake.ts
/* typeorm/src/decorator/columns/ */
export function Column(): Function;
export function Column(type: any): Function;
export function Column(options: any): Function;
export function Column(type: any, options: any): Function;
export function Column(typeOrOptions?: any, options?: any): Function {
return function (object: Object, propertyName: string) {};
}
export function CreateDateColumn(options?: any): Function {
return function (object: Object, propertyName: string) {};
}
export function DiscriminatorColumn(discriminatorOptions: any): Function {
return function (target: Function) {};
}
export function PrimaryGeneratedColumn(options?: any): Function {
return function (object: Object, propertyName: string) {};
}
export function PrimaryColumn(options?: any): Function;
export function PrimaryColumn(type?: any, options?: any): Function;
export function PrimaryColumn(typeOrOptions?: any, options?: any): Function {
return function (object: Object, propertyName: string) {};
}
export function UpdateDateColumn(options?: any): Function {
return function (object: Object, propertyName: string) {};
}
export function VersionColumn(options?: any): Function {
return function (object: Object, propertyName: string) {};
}
/* typeorm/src/decorator/listeners/ */
export function AfterInsert() {
return function (object: Object, propertyName: string) {};
}
export function AfterLoad() {
return function (object: Object, propertyName: string) {};
}
export function AfterRemove() {
return function (object: Object, propertyName: string) {};
}
export function AfterUpdate() {
return function (object: Object, propertyName: string) {};
}
export function BeforeInsert() {
return function (object: Object, propertyName: string) {};
}
export function BeforeRemove() {
return function (object: Object, propertyName: string) {};
}
export function BeforeUpdate() {
return function (object: Object, propertyName: string) {};
}
export function EventSubscriber() {
return function (target: Function) {};
}
/* typeorm/src/decorator/options/ */
export function JoinColumn(options?: any): Function {
return function (object: Object, propertyName: string) {};
}
export function JoinTable(options?: any): Function {
return function (object: Object, propertyName: string) {};
}
export function ManyToMany<T>(typeFunction: any, options?: any): Function;
export function ManyToMany<T>(typeFunction: any,
inverseSide?: any,
options?: any): Function;
export function ManyToMany<T>(typeFunction: any,
inverseSideOrOptions?: any,
options?: any): Function {
return function (object: Object, propertyName: string) {};
}
export function ManyToOne<T>(typeFunction: any, options?: any): Function;
export function ManyToOne<T>(typeFunction: any,
inverseSide?: any,
options?: any): Function;
export function ManyToOne<T>(typeFunction: any,
inverseSideOrOptions?: any,
options?: any): Function {
return function (object: Object, propertyName: string) {};
}
export function OneToMany<T>(typeFunction: any,
inverseSide: any,
options?: any): Function;
export function OneToMany<T>(typeFunction: any,
inverseSideOrOptions: any,
options?: any): Function {
return function (object: Object, propertyName: string) {};
}
export function OneToOne<T>(typeFunction: any, options?: any): Function;
export function OneToOne<T>(typeFunction: any,
inverseSide?: any,
options?: any): Function;
export function OneToOne<T>(typeFunction: any,
inverseSideOrOptions?: any,
options?: any): Function {
return function (object: Object, propertyName: string) {};
}
export function RelationCount<T>(relation: any): Function {
return function (object: Object, propertyName: string) {};
}
export function RelationId<T>(relation: any): Function {
return function (object: Object, propertyName: string) {};
}
/* typeorm/src/decorator/tables/ */
export function AbstractTable() {
return function (target: Function) {};
}
export function ClassTableChild(tableName?: any, options?: any) {
return function (target: Function) {};
}
export function ClosureTable(name?: any, options?: any) {
return function (target: Function) {};
}
export function EmbeddableTable(): Function {
return function (target: Function) {};
}
export function SingleTableChild() {
return function (target: Function) {};
}
export function Table(name?: any, options?: any) {
return function (target: Function) {};
}
export function TableInheritance(type: any) {
return function (target: Function) {};
}
/* typeorm/src/decorator/tree/ */
export function TreeChildren(options?: any): Function {
return function (object: Object, propertyName: string) {};
}
export function TreeLevelColumn(): Function {
return function (object: Object, propertyName: string) {};
}
export function TreeParent(options?: any): Function {
return function (object: Object, propertyName: string) {};
}
/* typeorm/src/decorator/ */
export function DiscriminatorValue(value: any): Function {
return function (target: Function) {};
}
export function Embedded<T>(typeFunction: any) {
return function (object: Object, propertyName: string) {};
}
export function Index(options?: any): Function;
export function Index(name: any, options?: any): Function;
export function Index(name: any, fields: any, options?: any): Function;
export function Index(fields: any, options?: any): Function;
export function Index(fields: any, options?: any): Function;
export function Index(name: any, fields: any, options?: any): Function;
export function Index(nameOrFields: any,
maybeFieldsOrOptions?: any,
maybeOptions?: any): Function {
return function (clsOrObject: Function|Object, propertyName?: string) {};
}
export function NamingStrategy(name?: any): Function {
return function (target: Function) {};
}
from typeorm.
I didn't get what is your suggestion here? (because I have no idea how to handle this situation)
from typeorm.
Essentially, if you write the decorators as interfaces then using them in a FE application means we won't have to import the Node dependencies
from typeorm.
My suggestion with typeorm-fake is a hacky fix. It looks like you have an IDEA comment already in place that may solve this issue. src/metadata/EntityMetadata.ts importing LazyRelationsWrapper seems to be the only library, when loading a decorator, that requires a db connection. I believe if you implemented your // todo: IDEA. store all entity metadata in the EntityMetadata too? (this will open more features for metadata objects + no need to access connection in lot of places)
Since the problem is accessing any sort of db connection from the client side.
from typeorm.
if you write the decorators as interfaces
@TylerDev6 can you please tell more about this implementation? I didn't get what do you mean by "decorators as interfaces"
@strictd why did you talk about LazyRelationsWrapper? Is problem there? I thought problem in decorators
from typeorm.
Ok in my current development setup. I have a single src/ directory that is broken down into;
src/api
src/browser
src/mobile
src/models
src/providers
I am using typescripted classes from src/models for all components, frontend and backend.
browser view (typescript/ng2),
mobile view (typescript/ng2/ionic2),
api server (typescript/express/typeorm)
Since i'm using one set of models for both frontend and backend, when the frontend attempts to import { Table, Column } from 'typeorm'; typeorm attempts to use the connection manager, which from a client side isn't possible. Following down the chain of declaration imports, i've found one place where LazyRelationsWrapper is getting imported and through that import requires the use of the connection manager, which is unavailable from a frontend component.
from typeorm.
generally I don't recommend people to use shared model between frontend and backend, because of such issues. I have no idea how to resolve this issue properly, because even if we resolve some issue in LazyRelationsWrapper
frontend will load all other unnecessary dependencies.
For now fake "mapping" file as you created for webpack seems best solution, but yeah its very big monkey patch. I would like to find better solution, but nothing comes to my mind
from typeorm.
@strictd I have forked the repo and created ionic-orm -will work in angularjs2 as well.. just primarily for me to do it in Cordova/Ionic2 platform. We can use this on the client side. So far it's only supporting WebSQL. SQLite for the Apache Cordova plugin in coming soon. Feel free to check it out.
ionic-orm
I hope that one day we can get TypeORM to be modularized in a way where we could have it in the same repo..
from typeorm.
@BradyLiles provide a plan how to make it modularized (what changes are needed) and lets investigate on this side
from typeorm.
I completely agree. Let's take this one offline. I'll Skype you.
from typeorm.
we havent talk too much with @BradyLiles about it, but I hope if he'll have some progress on this issue and create a PR against typeorm. If not, I'll have my own plans to implement these things in the future.
from typeorm.
@strictd do you still use typeorm-fake.ts
file? Can you checkout this . This file will generate:
// columns
/* export */ function Column(typeOrOptions, options) {
return function (object, propertyName) {
};
}
/* export */ function CreateDateColumn(options) {
return function (object, propertyName) {
};
}
/* export */ function DiscriminatorColumn(discriminatorOptions) {
return function (object, propertyName) {
};
}
/* export */ function PrimaryColumn(typeOrOptions, options) {
return function (object, propertyName) {
};
}
/* export */ function PrimaryGeneratedColumn(options) {
return function (object, propertyName) {
};
}
/* export */ function UpdateDateColumn(options) {
return function (object, propertyName) {
};
}
/* export */ function VersionColumn(options) {
return function (object, propertyName) {
};
}
// listeners
/* export */ function AfterInsert() {
return function (object, propertyName) {
};
}
/* export */ function AfterLoad() {
return function (object, propertyName) {
};
}
/* export */ function AfterRemove() {
return function (object, propertyName) {
};
}
/* export */ function AfterUpdate() {
return function (object, propertyName) {
};
}
/* export */ function BeforeInsert() {
return function (object, propertyName) {
};
}
/* export */ function BeforeRemove() {
return function (object, propertyName) {
};
}
/* export */ function BeforeUpdate() {
return function (object, propertyName) {
};
}
/* export */ function EventSubscriber() {
return function (object, propertyName) {
};
}
// relations
/* export */ function JoinColumn(options) {
return function (object, propertyName) {
};
}
/* export */ function JoinTable(options) {
return function (object, propertyName) {
};
}
/* export */ function ManyToMany(typeFunction, inverseSideOrOptions, options) {
return function (object, propertyName) {
};
}
/* export */ function ManyToOne(typeFunction, inverseSideOrOptions, options) {
return function (object, propertyName) {
};
}
/* export */ function OneToMany(typeFunction, inverseSideOrOptions, options) {
return function (object, propertyName) {
};
}
/* export */ function OneToOne(typeFunction, inverseSideOrOptions, options) {
return function (object, propertyName) {
};
}
/* export */ function RelationCount(relation) {
return function (object, propertyName) {
};
}
/* export */ function RelationId(relation) {
return function (object, propertyName) {
};
}
// tables
/* export */ function AbstractTable() {
return function (object) {
};
}
/* export */ function ClassTableChild(tableName, options) {
return function (object) {
};
}
/* export */ function ClosureTable(name, options) {
return function (object) {
};
}
/* export */ function EmbeddableTable() {
return function (object) {
};
}
/* export */ function SingleTableChild() {
return function (object) {
};
}
/* export */ function Table(name, options) {
return function (object) {
};
}
/* export */ function TableInheritance(type) {
return function (object) {
};
}
// tree
/* export */ function TreeChildren(options) {
return function (object, propertyName) {
};
}
/* export */ function TreeLevelColumn() {
return function (object, propertyName) {
};
}
/* export */ function TreeParent(options) {
return function (object, propertyName) {
};
}
//# sourceMappingURL=decorators-shim.js.map
and if you include it as like a shim in index.html like this:
<script src="node_modules/typeorm/decorators-shim.js"></script>
will it work 100% and resolve all problems?
from typeorm.
This is what I have been doing with typeorm-fake.ts for the time being.
I have a common lib project where I put the models and other common functionality.
In my models I have
import {Table, Column, PrimaryColumn, OneToOne} from "./typeorm";
...
then in ./typeorm.ts I have
export * from "typeorm"
and I have a file called buildClient.sh which does this
echo 'export * from "./typeorm-fake"' > src/entities/typeorm.ts;
tsc;
echo 'export * from "typeorm"' > src/entities/typeorm.ts;
Then in the package.json for my client application I have
...
"dependencies": {
"project-lib": "file:///Users/Michael/Git/project-lib",
...
},
...
so after running buildClient.sh in the lib project I do 'npm install' in the client project which imports the shim file. Then back in the lib project I run tsc to put it back to the actual typeorm. This way I can run 'npm link ../project-lib' in my server project.
I think the build tools for react-native and nativescript traverse all the require() statements in the compiled js files and if fs or any node-specific modules are hit it errors out because it cant find the modules. So for me importing a script shim wont work because there is no place i can put a script tag.
Edit: Also I found out if you do this you need to export connection from the typeorm you imported in your lib project, otherwise your server project will have a different instance of connection and it wont be able to find the metadata for your models. So essentially my server project has no dependency on typeorm, only project-lib which has a dependency on typeorm
from typeorm.
this feature released in 0.0.7-alpha.22
. Look here to understand how it works. I'll need to add some documentation for this feature.
from typeorm.
Hate to bring up an old thread, but i've got a related question.
I'm currently bundling some functionality into my user model (the validatePassword()
function, which returns a bool. It would be extra cool if it were possible to import my model into the React code and re-use that function in a form. I realize I could break the function off of the model, but it's convenient to have everything bundled together if possible.
import { User } from '../../entity'
// ...
const u = new User()
u.validatePassword(this.state.password)
Currently getting a webpack missing module error: Uncaught Error: Cannot find module "fs"
. Is there a known way to handle this?
from typeorm.
So, you want to reuse models on the frontend, right? If yes, then did you map typeorm package to the shim in webpack config? If yes, then what gives you this error?
from typeorm.
Ah sorry, I didn't read the comments closely on the webpack thing and had it pointed incorrectly. Even when fixed, it still complains about fs
from mongo (which is included in one of my classes so that I can use new ObjectId(id)
for queries.
In any case, I don't it's a typeorm issue. thanks for the 👀, sorry for false alarm!
from typeorm.
@RDeluxe I do not see how this is related to typeorm
from typeorm.
Related Issues (20)
- Tree Entities can query the tree, but the result is unordered and a sorting parameter should be added
- Add support for ParadeDB Postgres
- The new typeorm version is not compatible with the mongodb driver package version 6.x.x HOT 3
- TreeRepository does not update mpath if parentId was soft-deleted
- Entity instance is not correctly initialized inside .save() method
- Updating a parent of a record with children to a new parent closure table
- Repository.prototype.save results for geography types are not consistent with find methods
- typeorm query spesific selecion HOT 1
- typeorm TypeError: Cannot read properties of undefined (reading 'type')
- TypeORM Migration Bug: Duplicate Index Names in Generated Migration
- The getPendingMigrations creates migrations table
- Bug: ORDER BY NULLS (FIRST | LAST) for SQLServer
- Issues with migrations after upgrading typeorm from 0.2.31 to 0.3.20
- Similar tests with identical titles
- prettier should be enforced in circleci
- Instead of experimental decorators use the full version of decorators introduced in TS 5.0 HOT 1
- Postgres geometry column is always being altered to type geometry in every migration despite already being type geometry
- QueryFailedError: read ECONNRESET HOT 7
- Using transactions in tests w/ NestJS & TypeORM
- QueryBuilder looks up the wrong joinAttr when entities have identical property names
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from typeorm.