Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot use import statement outside a module #324

Closed
nodegin opened this issue Mar 27, 2024 · 13 comments · Fixed by #339
Closed

Cannot use import statement outside a module #324

nodegin opened this issue Mar 27, 2024 · 13 comments · Fixed by #339

Comments

@nodegin
Copy link

nodegin commented Mar 27, 2024

After upgrading to latest release (7.0.0), I got this error:

/Users/user/Desktop/project/node_modules/@jorgebodega/typeorm-seeding/dist/cli.js:2
import { bootstrap } from './commands/seed.command';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at internalCompileFunction (node:internal/vm:77:18)
    at wrapSafe (node:internal/modules/cjs/loader:1290:20)
    at Module._compile (node:internal/modules/cjs/loader:1342:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1437:10)
    at Object.require.extensions.<computed> [as .js] (/Users/user/Desktop/project/node_modules/ts-node/src/index.ts:1608:43)
    at Module.load (node:internal/modules/cjs/loader:1212:32)
    at Function.Module._load (node:internal/modules/cjs/loader:1028:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:142:12)
    at phase4 (/Users/user/Desktop/project/node_modules/ts-node/src/bin.ts:649:14)
    at bootstrap (/Users/user/Desktop/project/node_modules/ts-node/src/bin.ts:95:10)
@rashgaroth
Copy link

Hey @nodegin you can use this lib as an executor, mine was fixed when use this lib.

package.json:

    "typeorm": "tsx ./node_modules/typeorm/cli",
    "seeding": "tsx ./node_modules/@jorgebodega/typeorm-seeding/dist/cli",
    "migration:generate": "npm run typeorm -- -d ./src/db/typeorm.config.ts migration:generate ./src/db/migrations/$npm_config_name",
    "migration:run": "npm run typeorm -- -d ./src/db/typeorm.config.ts migration:run",
    "migration:revert": "npm run typeorm -- -d ./src/db/typeorm.config.ts migration:revert",
    "seed:run": "npm run seeding -- seed -d ./src/db/typeorm.config.ts ./src/db/seeds/*.ts"

terminal:

npm run seed:run

@alumni
Copy link

alumni commented Apr 19, 2024

v7 switched from CommonJS to ESM. It is not mentioned in the breaking changes, but it is a breaking change for projects that are using CommonJS

@jorgebodega
Copy link
Owner

As far as I tried, I did not change anything to be ESM-only (TypeORM is still supporting CommonJS).

If you are sure of this problem, a PR would be appreciated.

@alumni
Copy link

alumni commented Apr 19, 2024

Introduced by PR #303 in tsconfig.json by changing:
compilerOptions.module: node16 (v6) -> es2022 (v7)

This change replaced the requires with imports. It's true that package.json doesn't contain type: module, so the package is still CommonJS, but the scripts are using ESM imports.

Probably the best option for consistency would be to use node16 or nodenext when transpiling: https://www.typescriptlang.org/tsconfig#module. If you take a look at @tsconfig/node20, they are using module: node16.

@alumni
Copy link

alumni commented Apr 19, 2024

Normally since it's a CLI tool, it shouldn't matter whether it's CommonJS or ESM, but it does if you are forced to call dist/cli.js directly from your own project. We do that because both the seeds and the typeorm config are written in TypeScript, so we are executing e.g. ts-node typeorm-seeding/dist/cli.js *.seed.ts -d ormconfig.ts.

Later edit: ts-node supports --esm (and it also provides ts-node-esm), so probably not a big deal, will need to check if it solves the issue for me.

@alumni
Copy link

alumni commented Apr 19, 2024

ts-node --esm does not work (obviously) and tsx doesn't work either because it uses esbuild which is not good at transpiling TypeScript (especially decorators in the TypeORM entities).

I'll update the tsconfig.json to use tsconfig/node18 probably and submit a PR.

@alumni
Copy link

alumni commented Apr 22, 2024

Since neither ts-node nor tsx are working and since ESM imports in CommonJS modules are not allowed anyway, I opened PR #325 to set the TypeScript target module type back to node16 (auto-detect, based on package.json config) instead of es2022 (forced ESM). This changes the ESM imports back to CJS requires and solves this issue.

In general, I would not change from node16 to anything else since this is the option that detects the module type automatically (unless multiple compilation targets are needed, e.g. to publish both CJS and ESM in one package).

@alumni
Copy link

alumni commented Apr 25, 2024

@jorgebodega/typeorm-factory has the same issue.

@iNewLegend
Copy link

You may don't need anything at all. at least some typescript runner eg bun

// create-users.ts

import dataSource from "@demo-app/backend/db/seeds/datasource";

import { UsersEntity } from "@demo-app/backend/src/users/users.entity";

const users: Partial<UsersEntity>[] = [ {
    email: "test@test.gmail.com",
    password: "test",
} ];

await dataSource.createEntityManager().save(
    users.map( user => Object.assign( new UsersEntity(), user ) )
);
// datasource.ts

import { DataSource } from "typeorm";

import DatabaseConfig from "@demo-app/backend/config/database.config";

const dataSource = await ( new DataSource( DatabaseConfig ) ).initialize();

export default dataSource;
// database.config.ts

import { UsersEntity } from "@demo-app/backend/src/users/users.entity";

import type { TypeOrmModuleOptions } from "@nestjs/typeorm";

const config : TypeOrmModuleOptions  = {
    type: "sqlite",
    database: "db/database.sqlite",
    logging: "all",
    logger: "advanced-console",
};

function shouldSynchronize( config: TypeOrmModuleOptions ) {
    // If database exists, do not synchronize
    if ( "sqlite" === config.type ) {
        return ! require( "fs" ).existsSync( config.database );
    }

    // TODO: Implement for other database types
    return false;
}

export default {
    ...config,

    entities: [ UsersEntity ],
    synchronize: shouldSynchronize( config ),
};
 bun run --bun create-users.ts

@alumni
Copy link

alumni commented Jul 1, 2024

FYI bun doesn't work properly with TypeORM.

Or rather, TypeORM has some incorrect package.json config that makes bun interpret imports incorrectly. See oven-sh/bun#7633 or a few other tickets in the bun repo.

@duongductrong
Copy link

Hey @nodegin you can use this lib as an executor, mine was fixed when use this lib.

package.json:

    "typeorm": "tsx ./node_modules/typeorm/cli",
    "seeding": "tsx ./node_modules/@jorgebodega/typeorm-seeding/dist/cli",
    "migration:generate": "npm run typeorm -- -d ./src/db/typeorm.config.ts migration:generate ./src/db/migrations/$npm_config_name",
    "migration:run": "npm run typeorm -- -d ./src/db/typeorm.config.ts migration:run",
    "migration:revert": "npm run typeorm -- -d ./src/db/typeorm.config.ts migration:revert",
    "seed:run": "npm run seeding -- seed -d ./src/db/typeorm.config.ts ./src/db/seeds/*.ts"

terminal:

npm run seed:run

Thank you, we can follow this temp solution to fix this

@alumni
Copy link

alumni commented Jul 22, 2024

tsx and bun didn't work for my for the reasons specified above. My current solution was to update to 7.1.0-next.1 and patch the dynamic import in commandUtils.js until this is properly fixed.

diff --git a/dist/utils/commandUtils.js b/dist/utils/commandUtils.js
index 0a922d09f28843382e947501307f775b4181a1f3..febe6d3d13660918072d81c6de0aad19228f1356 100644
--- a/dist/utils/commandUtils.js
+++ b/dist/utils/commandUtils.js
@@ -8,7 +8,7 @@ async function loadDataSource(dataSourceFilePath) {
     return CommandUtils_1.CommandUtils.loadDataSource(dataSourceFilePath);
 }
 async function loadSeeders(seederPaths) {
-    const seederFileExports = (await Promise.all(seederPaths.map((seederFile) => import(seederFile))))
+    const seederFileExports = (await Promise.all(seederPaths.map((seederFile) => Promise.resolve().then(() => require(seederFile)))))
         .map((seederExport) => seederExport.default?.default ?? seederExport.default)
         .filter((seederExport) => Boolean(seederExport));
     if (seederFileExports.length === 0) {

Instead of the dynamic import, the actual solution would be to use importOrRequireFile from typeorm/util/ImportUtils - then the seeders would be loaded in the same way ormconfig, entities, subscribers and migrations are loaded.

Or even better, we could completely rely on TypeORM for loading the classes from the globs, using importClassesFromDirectories (from typeorm/util/DirectoryExportedClassesLoader).

alumni added a commit to alumni/typeorm-seeding that referenced this issue Jul 22, 2024
alumni added a commit to alumni/typeorm-seeding that referenced this issue Jul 22, 2024
@alumni
Copy link

alumni commented Jul 22, 2024

I just opened two PRs, #338 and #339.

I prefer #339 since it relies on more on TypeORM build-in functions, so there's less code in this repo to maintain.

alumni added a commit to alumni/typeorm-seeding that referenced this issue Sep 26, 2024
alumni added a commit to alumni/typeorm-seeding that referenced this issue Sep 26, 2024
github-actions bot pushed a commit that referenced this issue Oct 4, 2024
# [7.1.0-next.3](v7.1.0-next.2...v7.1.0-next.3) (2024-10-04)

### Bug Fixes

* load seeders classes using typeorm ([#324](#324)) ([#339](#339)) ([a2590cc](a2590cc))
github-actions bot pushed a commit that referenced this issue Oct 4, 2024
# [7.1.0](v7.0.0...v7.1.0) (2024-10-04)

### Bug Fixes

* load seeders classes using typeorm ([#324](#324)) ([#339](#339)) ([a2590cc](a2590cc))
* update dependency glob to v11 ([#342](#342)) ([e5fb787](e5fb787))

### Features

* install biome as formatter and linter ([#335](#335)) ([a195c27](a195c27))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants