使用“嵌套新”命令启动新项目。正常工作,直到我向其中添加实体文件。
出现以下错误:
从“ typeorm”导入{实体,列,PrimaryGeneratedColumn};
^^^^^^^
SyntaxError:无法在模块外部使用import语句
我想念什么?
将实体添加到模块:
import { Module } from '@nestjs/common';
import { BooksController } from './books.controller';
import { BooksService } from './books.service';
import { BookEntity } from './book.entity';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [TypeOrmModule.forFeature([BookEntity])],
controllers: [BooksController],
providers: [BooksService],
})
export class BooksModule {}
app.module.ts:
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Connection } from 'typeorm';
import { BooksModule } from './books/books.module';
@Module({
imports: [TypeOrmModule.forRoot()],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
答案 0 :(得分:28)
我的假设是您具有一个TypeormModule
属性的entities
配置,如下所示:
entities: ['src/**/*.entity.{ts,js}']
或喜欢
entities: ['../**/*.entity.{ts,js}']
您收到的错误是因为您试图在ts
上下文中导入js
文件。只要您不使用webpack,就可以使用它来获取正确的文件
entities: [join(__dirname, '**', '*.entity.{ts,js}`)]
其中join
是从path
模块导入的。现在__dirname
将解析为src
或dist
,然后分别找到预期的ts
或js
文件。让我知道是否仍然存在问题。
以上内容假设配置是通过javascript兼容文件完成的(.js
或在TypeormModule.forRoot()
传递的参数中)。如果您使用的是ormconfig.json
,则应使用
entities: ['dist/**/*.entity.js']
,以便您使用已编译的js文件,而没有机会在代码中使用ts文件。
答案 1 :(得分:14)
在TypeORM文档中,我找到了Typescript的特定部分。
本节说:
全局安装ts-node:
npm install -g ts-node
在package.json的脚本部分下添加typeorm命令
"scripts" { ... "typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js" }
然后您可以运行以下命令:
npm run typeorm migration:run
如果需要将带有破折号的参数传递给npm脚本,则需要 在-之后添加它们。例如,如果您需要生成, 命令是这样的:
npm run typeorm migration:generate -- -n migrationNameHere
这适用于我的文件配置:
{
"type": "postgres",
"host": "yourhost",
"port": 5423,
"username": "username",
"password": "password",
"database": "your_db",
"synchronize": true,
"entities": [
"src/modules/**/*.entity.{ts,js}"
],
"migrations": [
"src/migrations/**/*.{ts,js}"
],
"cli": {
"entitiesDir": "src/modules",
"migrationsDir": "src/migrations"
}
}
然后您可以运行generate命令。
答案 2 :(得分:9)
正如Jay McDoniel在回答中解释的那样,问题似乎出在ormconfig.json
文件中的实体文件的模式匹配:可能是从javascript文件(大概是先前编译的打字稿文件)导入了打字稿文件(模块) )。
删除ts
中现有的ormconfig.json
全局模式就足够了,以便TypeORM仅加载javascript文件。实体文件的路径应相对于执行节点的工作目录。
"entities" : [
"dist/entity/**/*.js"
],
"migrations" : [
"dist/migration/**/*.js"
],
"subscribers": [
"dist/subscriber/**/*.js"
],
答案 3 :(得分:4)
这就是我设法修复它的方式。使用单个配置文件,我可以在应用程序 boostrap 或使用 TypeOrm 的 CLI 上运行迁移。
src/config/ormconfig.ts
import parseBoolean from '@eturino/ts-parse-boolean';
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
import * as dotenv from 'dotenv';
import { join } from 'path';
dotenv.config();
export = [
{
//name: 'default',
type: 'mssql',
host: process.env.DEFAULT_DB_HOST,
username: process.env.DEFAULT_DB_USERNAME,
password: process.env.DEFAULT_DB_PASSWORD,
database: process.env.DEFAULT_DB_NAME,
options: {
instanceName: process.env.DEFAULT_DB_INSTANCE,
enableArithAbort: false,
},
logging: parseBoolean(process.env.DEFAULT_DB_LOGGING),
dropSchema: false,
synchronize: false,
migrationsRun: parseBoolean(process.env.DEFAULT_DB_RUN_MIGRATIONS),
migrations: [join(__dirname, '..', 'model/migration/*.{ts,js}')],
cli: {
migrationsDir: 'src/model/migration',
},
entities: [
join(__dirname, '..', 'model/entity/default/**/*.entity.{ts,js}'),
],
} as TypeOrmModuleOptions,
{
name: 'other',
type: 'mssql',
host: process.env.OTHER_DB_HOST,
username: process.env.OTHER_DB_USERNAME,
password: process.env.OTHER_DB_PASSWORD,
database: process.env.OTHER_DB_NAME,
options: {
instanceName: process.env.OTHER_DB_INSTANCE,
enableArithAbort: false,
},
logging: parseBoolean(process.env.OTHER_DB_LOGGING),
dropSchema: false,
synchronize: false,
migrationsRun: false,
entities: [],
} as TypeOrmModuleOptions,
];
src/app.module.ts
import configuration from '@config/configuration';
import validationSchema from '@config/validation';
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import { LoggerService } from '@shared/logger/logger.service';
import { UsersModule } from '@user/user.module';
import { AppController } from './app.controller';
import ormconfig = require('./config/ormconfig'); //path mapping doesn't work here
@Module({
imports: [
ConfigModule.forRoot({
cache: true,
isGlobal: true,
validationSchema: validationSchema,
load: [configuration],
}),
TypeOrmModule.forRoot(ormconfig[0]), //default
TypeOrmModule.forRoot(ormconfig[1]), //other db
LoggerService,
UsersModule,
],
controllers: [AppController],
})
export class AppModule {}
package.json
"scripts": {
...
"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js --config ./src/config/ormconfig.ts",
"typeorm:migration:generate": "npm run typeorm -- migration:generate -n",
"typeorm:migration:run": "npm run typeorm -- migration:run"
},
项目结构
src/
├── app.controller.ts
├── app.module.ts
├── config
│ ├── configuration.ts
│ ├── ormconfig.ts
│ └── validation.ts
├── main.ts
├── model
│ ├── entity
│ ├── migration
│ └── repository
├── route
│ └── user
└── shared
└── logger
答案 4 :(得分:2)
我接下来在 tsconfig.json 文件中进行了更改:
"module": "es6"
收件人:
"module": "commonjs",
对我有帮助
答案 5 :(得分:1)
您需要为应用程序的每个部分都具有一个something.module.ts。它的工作原理类似于Angular。这是使用GraphQL解析器和服务设置的。 REST与控制器有些不同。每个模块可能会有一个实体,如果是GraphQL,则可能有projects.schema.graphql。
projects.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ProjectsService } from './projects.service';
import { Projects } from './projects.entity';
import { ProjectsResolvers } from './projects.resolvers';
@Module({
imports: [
TypeOrmModule.forFeature([Projects])],
providers: [
ProjectsService,
ProjectsResolvers
],
})
export class ProjectsModule {}
答案 6 :(得分:1)
如官方文档中所述,在ormconfig.json
中定义entities属性为我解决了这个问题。
// This is your ormconfig.json file
...
"entities": ["dist/**/*.entity{.ts,.js}"]
...
答案 7 :(得分:1)
这对我有用-无需更改您的ormconfig.js
。从您的node_modules
所在的根目录运行:
ts-node ./node_modules/typeorm/cli.js migration:generate -n <MirgrationName> -c <ConnectionType>
示例:
ts-node ./node_modules/typeorm/cli.js migration:create -n AuthorHasMultipleBooks -c development
答案 8 :(得分:1)
实际上,默认情况下,typeorm旨在与javascript一起使用。
要使用typescript运行迁移,必须告诉typeorm进行。
只需在下面这一行的脚本部分中放入您的package.json:
"typeorm": "ts-node-dev ./node_modules/typeorm/cli.js"
,然后尝试再次迁移:
yarn typeorm migration:run
答案 9 :(得分:1)
与其他人的评论一致 - 实际上,必须依赖生成的代码才能使其工作似乎很愚蠢。我不相信这个解决方案,因为它是其他人的存储库,但它实际上只允许完整的 Typescript 迁移。它依赖于 .env
文件 Typeorm 值而不是 ormconfig.json
虽然我确信它可以被翻译。我发现它有助于我消除对 .js
文件的依赖。
这里是回购: https://github.com/mthomps4/next-now-test/tree/next-typeorm-example
工作原理说明:
除了通常的 .env 或 ormconfig.json 文件,其中包含正确的 localhost db 连接,您还需要在 ormconfig.json 或 .env 文件中正确指定以下内容
TYPEORM_ENTITIES="entities/*.ts"
TYPEORM_MIGRATIONS="migrations/*.ts"
TYPEORM_ENTITIES_DIR="entities"
TYPEORM_MIGRATIONS_DIR="migrations"
注意实体和迁移全局只有 *.ts
。另一个非常重要的部分是如何设置您的 npm 脚本以与 ts-node
一起运行。
您需要一个扩展的 tsconfig,其中包含以下内容:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs"
}
}
这就是允许 ts-node 在生成迁移时正确“拾取” .ts 文件的原因。
这个 npm 脚本(DOTENV 部分仅在使用 .env 文件而不是 ormconfig.json
时)指定使用 tsconfig.json
"local": "DOTENV_CONFIG_PATH=./.env ts-node -P ./tsconfig.yarn.json -r dotenv/config"
它被用作“前体”脚本:
"typeorm:local": "yarn local ./node_modules/typeorm/cli.js"
我不是 100% 确定所有这些都是必要的(您可以全部内联完成),但它对我有用。基本上这表示“使用特定的 .env 文件和特定的 tsconfig 在 ts-node 的上下文中调用 typrorm cli。”在某些情况下,您可以跳过这些配置。
最后,这个脚本现在可以工作了:
"g:migration": "yarn typeorm:local migration:generate -n"
所以通过运行:
npm run g:migration -- User
您将获得基于您当前更改的实体自动生成的迁移文件!
所以 3 个嵌套的 npm 脚本之后,我们有一种非常具体的方法来运行“生成”迁移命令,并使用所有正确的配置来仅使用 TS 文件。是的 - 难怪有些人仍然反对打字稿,但幸运的是,这确实有效,如果您想尝试一下,看看它是如何“正常工作”的话,上面的示例存储库已经预先配置了所有内容。
答案 10 :(得分:0)
当我遇到此问题时,我正在将Node.js与Typescript和TypeORM一起使用。在ormconfig.json文件中进行配置对我有用。
entities: ['dist/**/*.entity.js']
我的ormconfig.json文件的完整代码:
{
"type": "mysql",
"host": "localhost",
"port": 3306,
"username": "xxxxxxxx",
"password": "xxxxxxxx",
"database": "typescript_orm",
"synchronize": true,
"logging": false,
"migrationTableName": "migrations",
"entities": [
"dist/**/*.entity.js"
],
"migrations": [
"src/migration/**/*.{ts, js}"
],
"suscribers": [
"src/suscriber/**/*.{ts, js}"
],
"cli": {
"entitiesDir": "src/model",
"migrationDir": "src/migration",
"suscribersDir": "src/suscriber"
}
}
答案 11 :(得分:0)
支持迁移的配置:
// FILE: src/config/ormconfig.ts
const connectionOptions: ConnectionOptions = {
// Other configs here
// My ormconfig isn't in root folder
entities: [`${__dirname}/../**/*.entity.{ts,js}`],
synchronize: false,
dropSchema: false,
migrationsRun: false,
migrations: [getMigrationDirectory()],
cli: {
migrationsDir: 'src/migrations',
}
}
function getMigrationDirectory() {
const directory = process.env.NODE_ENV === 'migration' ? 'src' : `${__dirname}`;
return `${directory}/migrations/**/*{.ts,.js}`;
}
export = connectionOptions;
// FILE package.json
{
// Other configs here
"scripts": {
"typeorm": "NODE_ENV=migration ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js --config src/config/database.ts",
"typeorm:migrate": "npm run typeorm migration:generate -- -n",
"typeorm:run": "npm run typeorm migration:run",
"typeorm:revert": "npm run typeorm migration:revert"
}
}
答案 12 :(得分:0)
如果您使用 typescript 编写并使用 tsc
创建一个包含已翻译 js 文件的 dist 文件夹,那么您可能遇到了我的问题,它会在此处得到解决。
正如 docs 中提到的,如果您使用 nodemon server.js
,那么您将从 js 的角度点击实体,并且它不会识别导入,因为它与 ts 和 es6 相关。但是,如果您想从 ts 文件中导入实体,您应该运行 ts-node server.ts
!
我个人认为前者node server.js
更安全,因为它更接近实际案例应用。
!!!然而 !!!请务必小心,因为如果更改实体名称,您必须删除 dist 文件夹并重建它,否则会引发错误或意外工作。
发生错误是因为 tsc
将尝试翻译更改和创建的 ts 文件并保留已删除的文件,以便它可以更快地运行!
我希望它有所帮助,因为它肯定会在未来帮助我,因为我几乎可以肯定我会再次忘记它!