melonJS icon indicating copy to clipboard operation
melonJS copied to clipboard

Typescript error since version 14: "File "../melonjs.module.d.ts" is not a module"

Open lartkma opened this issue 2 years ago • 16 comments

Describe the bug When using the latest version of melonjs in a Typescript project, trying to build the project generates an error by the Typescript transpiler.

To Reproduce

  1. Create this simple project using Typescript and Vite. The project consist of only 4 files in a folder:

package.json

{
  "name": "testmelon2ts",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview"
  },
  "devDependencies": {
    "typescript": "^4.9.3",
    "vite": "^3.2.3"
  },
  "dependencies": {
    "melonjs": "^13.4.0"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "ES6",
    "useDefineForClassFields": true,
    "module": "ES6",
    "lib": ["ES6", "DOM"],
    "moduleResolution": "Node",
    "strict": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "esModuleInterop": true,
    "noEmit": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "skipLibCheck": true,
    "allowJs": true
  },
  "include": ["src"]
}

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + TS</title>
  </head>
  <body>
    <h1>Welcome to MelonJS</h1>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>

src/main.ts

import * as me from 'melonjs';

me.device.onReady(() => {
  if(!me.video.init(1218, 562, {scale: 'auto'})) {
    alert('Your browser does not support HTML5 canvas');
    return;
  }

  me.game.world.addChild(new me.ColorLayer('background', '#0000BB'));
});
  1. Run npm install to install the packages.
  2. Run npm run build to run the Typescript transpiler. The process run successfully.
  3. Run npm run dev to deploy a test server. The result is the expected (a "Welcome to MelonJS" title and a blue scene)
  4. Update the melonjs library to the latest version (npm install melonjs@^14.0.0). You can also use any 14.x.x version.
  5. Run npm run build to run the Typescript transpiler. This time Typescript gives an error:
src/main.ts:1:21 - error TS2306: File '(project folder)/node_modules/melonjs/dist/melonjs.module.d.ts' is not a module.

1 import * as me from 'melonjs';
                      ~~~~~~~~~

Expected behavior The code should run and build normally like in the previous version, as according to the changelog there is no changes in the API used in this code.

Device information:

  • Device: PC
  • OS: Windows 10 Pro
  • Browser: Firefox
  • melonJS Version: 14.1.1
  • NodeJS Version: 19.1.0
  • NPM Version: 8.19.3

Additional context Running npm run dev with the updated melonjs runs the code correctly. Not sure why, as I'm not fully aware of how Vite works, but probably it's linked to some check disabled.

I don't think the issue is related to Vite, as I tried with a Webpack project with the same result.

I tried changing the values of "moduleResolution" and "module" in the tsconfig.json file to "NodeNext" but it didn't work

lartkma avatar Nov 23 '22 13:11 lartkma

I researched a bit and I found something interesting. The generated melonjs.module.d.ts contains several modules with an "index" module at the end. This StackOverflow question describes a similar situation, where the expected module name doesn't work. I tried the "fix" mentioned there: I modified the node_modules\melonjs\dist\melonjs.module.d.ts file in my project directly, replacing declare module "index" with declare module "melonjs". With that change, npm run build runs successfully.

While trying to understand the posted answer, I found this in the Typescript documentation (emphasis mine):

Note: outFile cannot be used unless module is None, System, or AMD. This option cannot be used to bundle CommonJS or ES6 modules.

lartkma avatar Nov 24 '22 03:11 lartkma

wow interesting, so basically it's because we are doing this : https://github.com/melonjs/melonJS/blob/master/package.json#L102

I thought it was a neat, clean & simple way to generate the d.ts file, but maybe we actually need a proper tsconfig.json file to generate it, instead of this quick "workaround"

obiot avatar Nov 24 '22 06:11 obiot

I think I found a possible solution: using --outdir instead of --outfile in the type generation command. I tried that in a local copy changing the types script in package.json, as well as the types property:

{
  "name": "melonjs",
  "version": "14.1.1",
  "description": "melonJS Game Engine",
  ....
  "main": "dist/melonjs.module.js",
  "module": "dist/melonjs.module.js",
  "types": "dist/types/index.d.ts",
  ....
  "scripts": {
    ....
    "types": "tsc src/index.js --declaration --allowJs --emitDeclarationOnly --outdir dist/types"
  }
}

After building the library and installing it in my demo project, npm run build runs successfully, without need for an special tsconfig.json configuration on neither the library project nor the demo project.

lartkma avatar Nov 30 '22 02:11 lartkma

I modified it to only generate one .d.ts file : "types": "tsc build/melonjs.module.js --declaration --allowJs --emitDeclarationOnly --outdir dist"

would this be working on your side ? I'd rather keep only one file instead of generating a separate file for every source file.

obiot avatar Nov 30 '22 06:11 obiot

the funny thing is that If I remember correctly, my version of the fix used to be the way we used to generate the .d.ts file initially, but then when we moved to a proper es6 build, we changed to generate the .d.ts file out of all separate files and therefore switch from outdir to outfile (; I might not remember correctly, but I'm pretty sure it was

obiot avatar Nov 30 '22 06:11 obiot

I modified it to only generate one .d.ts file : "types": "tsc build/melonjs.module.js --declaration --allowJs --emitDeclarationOnly --outdir dist"

would this be working on your side ? I'd rather keep only one file instead of generating a separate file for every source file.

I tried generating the library with this. At least I am able to build the demo project. But I've found the type suggestions in VSCode are more complete with my solution than with yours.

With tsc src/index.js ...: v1

With tsc build/melonjs.module.js ...: v2

I specifically tried this because it seems it happened before in #1071.

the funny thing is that If I remember correctly, my version of the fix used to be the way we used to generate the .d.ts file initially, but then when we moved to a proper es6 build, we changed to generate the .d.ts file out of all separate files and therefore switch from outdir to outfile (; I might not remember correctly, but I'm pretty sure it was

I think the commit that made the change you're talking about is this one https://github.com/melonjs/melonJS/commit/8410e65bc14875b93796d12281d034a7d7493656. It's noteworthy that the message of the commit says "no more missing API or modules", like what happens in the images...

I have no detailed knowledge of how ES6 modules or Typescript type generation works, so I don't know if there are other alternatives. But I feel that the note in the documentation about how --outFile "cannot be used to bundle CommonJS or ES6 modules" means that the multiple files approach is the way to go, IMHO.

lartkma avatar Dec 01 '22 02:12 lartkma

alright, separate files it is then ! I'll push the changes in the repo and publish a new version today !

thanks again really for your help on this

obiot avatar Dec 01 '22 03:12 obiot

14.1.2 published on NPM: https://www.npmjs.com/package/melonjs/v/14.1.2

let me know if it all works as expected now, and then I'll close this ticket :)

obiot avatar Dec 01 '22 08:12 obiot

I've just tested it. It allows me to build the Typescript test project successfully. However, I don't get any type suggestion when, for example, I'm using VS Code. I see the files generated by --outdir are commited in the repo, however, when I see what NPM has downloaded in node_modules, I only see the index file. I think you need to add them to the files array in package.json, right?

v3

lartkma avatar Dec 03 '22 01:12 lartkma

PD: When I try to build the melonJS library from the source, I get ESLint errors because it tries to parse non-code files. I worked around that locally adding "ignorePatterns": ["*.png", "*.frag", "*.vert"] to the .eslintrc.json file, but it's weird that you can build it without any problems. Maybe you have some system-level ESLint configurations?

lartkma avatar Dec 03 '22 01:12 lartkma

ok, now I remember why we switched to the build file to generate the ts definition. Reason being those files that are being converted to either base64 or JS/JSON before being "injected" into the final .js source code.

so at this stage I think we really need to add a tsconfig file that include "exclusions" for those files.

obiot avatar Dec 03 '22 08:12 obiot

Hi @lartkma, see the last commit, where I added a tsconfig file. rather than excluding the probllematic files, I included on the .js ones, let me know if it works for you with that configuration, but I think we should be good now :)

obiot avatar Dec 09 '22 04:12 obiot

@lartkma any feedback by any chance ?

obiot avatar Dec 13 '22 09:12 obiot

Hello. Sorry, I've been busy these days. I'll check it in the coming days.

El mar, 13 de dic. de 2022 4:26 a. m., Olivier Biot < @.***> escribió:

@lartkma https://github.com/lartkma any feedback by any chance ?

— Reply to this email directly, view it on GitHub https://github.com/melonjs/melonJS/issues/1162#issuecomment-1348032210, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAQVRE4PV4SFLFBWWQPOBNTWNA6KPANCNFSM6AAAAAASI6CXEY . You are receiving this because you were mentioned.Message ID: @.***>

lartkma avatar Dec 13 '22 11:12 lartkma

Hi, I'm new with melonJS I tried to install it on a Angular 14 App.

In the beginning I got some error like :

Error: node_modules/melonjs/dist/melonjs.module.d.ts:128:5 - error TS2416: Property 'resize' in type 'BitmapText' is not assignable to the same property in base type 'Renderable'.
  Type '(scale: number) => BitmapText' is not assignable to type '(w: number, h: number) => Rect'.
    Call signature return types 'BitmapText' and 'Rect' are incompatible.
      The types of 'scale(...).pos.onResetEvent' are incompatible between these types.
        Type '(x: number, y: number, z: number, settings: any) => ObservableVector3d' is not assignable to type '(x?: number | undefined, y?: number | undefined) => Vector2d'.

128     resize(scale: number): BitmapText;
        ~~~~~~

And :

Error: src/app/app.module.ts:3:21 - error TS2306: File '/home/pascal/Dev/melon/node_modules/melonjs/dist/melonjs.module.d.ts' is not a module.

3 import * as me from 'melonjs/dist/melonjs.module.js';
                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

And after some try I success to launch the "Hello World". Here my code : https://framagit.org/lascapi/melonjs-in-angular/

Thank's for your work :)

87113 avatar Dec 15 '22 20:12 87113

@lartkma any feedback by any chance ?

I've just tested it, and it seems to work. I can compile the test project and I got the type suggestions. You only need to make sure all the files generated in dist/types (and not only dist/types/index.d.ts) are packaged in the published version, elsewhere it won't work (or at least you won't get type suggestions)

lartkma avatar Dec 17 '22 03:12 lartkma

And after some try I success to launch the "Hello World". Here my code : https://framagit.org/lascapi/melonjs-in-angular/

Thank's for your work :)

that's awesome, sorry for the late reply (holiday mode is on already), and most probably I'll add a post in the forum linking back to this, so that we can keep a better trace of it somwhere.

obiot avatar Dec 23 '22 00:12 obiot

@lartkma any feedback by any chance ?

I've just tested it, and it seems to work. I can compile the test project and I got the type suggestions. You only need to make sure all the files generated in dist/types (and not only dist/types/index.d.ts) are packaged in the published version, elsewhere it won't work (or at least you won't get type suggestions)

sorry as well for the late reply, I'm off as well already for the holiday, but this is excellent !!!! Would you share your boilerplate ? I would love as well to make it the "official TS Boilerplate" for melonJS if possible.

obiot avatar Dec 23 '22 00:12 obiot

version 14.2 released, and the JS-ES6 boilerplate updated accordingly.; I'm closing this one as I believe we are done, but @lartkma (once you are back from the holiday break), my offer definitely still stand on have an official TS boilerplate :)

obiot avatar Dec 26 '22 03:12 obiot

@lartkma any feedback by any chance ?

I've just tested it, and it seems to work. I can compile the test project and I got the type suggestions. You only need to make sure all the files generated in dist/types (and not only dist/types/index.d.ts) are packaged in the published version, elsewhere it won't work (or at least you won't get type suggestions)

Hi @lartkma even though you did warn me, I managed to published the 14.2 version and forgot to update package.json to includes all the generated files. (see #1166)

so 14.3 on the way !

obiot avatar Dec 30 '22 01:12 obiot