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

The buildType option doesn't work yet. #168

Open
vixalien opened this issue Apr 29, 2024 · 11 comments
Open

The buildType option doesn't work yet. #168

vixalien opened this issue Apr 29, 2024 · 11 comments

Comments

@vixalien
Copy link

In the CLI, there's supposed to be an option called buildType to change the output format to just generate a .d.ts file, however that doesn't seem to be implemented yet.

Because of this, ts-for-gir can't really replace gi.ts right now

@JumpLink
Copy link
Collaborator

JumpLink commented May 3, 2024

@vixalien Unfortunately, we have not yet updated the documentation on the main branch, but hopefully this will happen soon. The option is still available in the 3.x branch. On the main branch the option has been removed, why do you need this to replace gi.ts?

@vixalien
Copy link
Author

vixalien commented May 3, 2024

We use gi.ts to generate typescript declaration files like the ones at https://gitlab.gnome.org/BrainBlasted/gi-typescript-definitions.

These files are included as submodules in apps where we can't use npm to install the types like Decibels and GNOME Sound Recorder.

I thought gi.js was being replaced by this so I thought this feature would be too much to miss.

@JumpLink
Copy link
Collaborator

JumpLink commented May 3, 2024

@vixalien I have removed the option because it should not absolutely necessary for your case and this simplifies the maintenance effort. You can still generate the types, with the difference that a separate folder is created for each generated type and a *.js and package.json are generated in addition to the *.d.ts (and other files like ambient imports etc) and dependencies are also imported using the package.json name.

However, the package.json is practical because it makes it easier to import the types, as typescript can then resolve this more easily. For this you need to add the path of your generated types (e.g. gi-typescript-definitions) and the types to the tsconfig.json like this:

{
  "compilerOptions": {   
    "baseUrl": "../gi-typescript-definitions",
    "types": ["gjs", "gio-2.0"],
    "module": "ESNext",
    "moduleResolution": "bundler"
  }
}

Alternatively you can use a package manager like npm, pnpm or yarn and add your types folder gi-typescript-definitions to the workspace of your package manager, this way the self-generated NPM packages should also be recognised.

Then TypeScript should know the types for the imports like this (thanks to the ambient module definitions included in this types):

import GLib from 'gi://GLib?version=2.0';

So no bundler is necessary to use the types in this way. However, a bundler can also be used if, for example, one is used anyway, in which case the types could also be imported in this way (but this is not necessarily):

import GLib from '@girs/glib-2.0';

The .js behind this package is then importing the real GJS module via import GLib from 'gi://GLib?version=2.0'; which should then be resolved by your bundler. This has the advantage that you do not have to add and maintain the types to tsconfig.json in this way.

So there should be several ways to use the self-generated types anyway. Or do you have such a special setup that this is not possible for you? Then please explain this to me in more detail, we are of course very interested in everyone being able to use the types. I haven't fully tested this without the package manager yet (but is tested using yarn workspaces), so problems are not excluded, if it doesn't work as I described, I would of course work on a solution 👍

Edit
I have adapted my text again to make it easier to read

@vixalien
Copy link
Author

vixalien commented May 5, 2024

GJS doesn't use package.json, so it is unused in our use-case

For this you need to add the path of your generated types (e.g. gi-typescript-definitions) and the types to the tsconfig.json like this:

This already worked with gi-typescript-definitions with the generated gi.d.ts file. This file serves as an index for all the packages. The gi.d.ts file was 9generated by applying this pending MR](https://gitlab.gnome.org/ewlsh/gi.ts/-/merge_requests/1)

The .js behind this package is then importing the real GJS module via import GLib from 'gi://GLib?version=2.0'; which should then be resolved by your bundler. This has the advantage that you do not have to add and maintain the types to tsconfig.json in this way.

When using GJS directly, there is no need for any .js file because GJS will resolve the GI imports directly.

All in all, the package.json and .js files tell me this is made for compatibility with node.js (presumably node-gtk). It also says in the README that support has been dropped for node-gtk, but we still have those files.

I strongly suspect that not generating these files (or at least adding an option not to) will ease the development process.

I have an example of an app where I use gi-typescript-definitions with a bundler (in this case, esbuild), and I told esbuild just not to resolve the gi://* files like this:

  external: ["gi://*", "format", "gettext"],

https://github.com/vixalien/muzika/blob/6c19937b127e7e968bccb03ca345e08bddf12085/lib/build.js#L25C1-L25C45

If you are using another bundler and the @girs/glib-2.0 import syntax, you can write a simple plugin for your bundler that would rewrite that import to gi://GLib-2.0.

I would also like to know if any apps import the types using the @girs/glib-2.0 from node

@JumpLink
Copy link
Collaborator

JumpLink commented May 6, 2024

@vixalien Thanks for the feedback, I have a few more questions about your use case: Do you write your sources in TypeScript? And if so, how do you transpile the sources to JavaScript? Do you use tsc for this? If so, how did you make it available on your system? I would have thought that there would be a dependency on Node.js anyway (and thus the use of NPM / package.json would not be a new dependency).

I know that GJS does not support package.json. In the suggestion I tried to explain, the package.json is not used at runtime but only in the previous process by tsc and/or esbuild.

For esbuild you just need to set the option bundle to true and add everything you don't want to bundle to external like gi:// and other imports you don't want to bundle. For the @girs/* imports the bundling process results in gi://* imports because that's what esbuild becomes from the .js files. But as I said, the @girs/* imports are optional anyway and you can also use the gi://* imports directly without loosing type definition support.

@JumpLink
Copy link
Collaborator

JumpLink commented May 6, 2024

I have now created a working example that shows how to generate the types by yourself and use them to create a simple GJS application with tsc and npm: https://github.com/gjsify/ts-for-gir-local-tsc-example

This example also uses the gi://* imports directly.

@JumpLink
Copy link
Collaborator

JumpLink commented May 6, 2024

And here an almost identical example, but uses esbuild instead of tsc to build the TypeScript code: https://github.com/gjsify/ts-for-gir-local-esbuild-example

The example also uses the direct gi://* imports, but thanks to esbuild they could be replaced with @girs/* imports and it would still work the same way.

@JumpLink
Copy link
Collaborator

JumpLink commented May 6, 2024

You can find more examples in the ts-for-gir repository, including some that use esbuild, Vite and Webpack as bundlers, with gi:// or @girs/* imports (so both usages are demonstrated). The examples in the ts-for-gir repository all are using yarn instead of npm, because we are using yarn for ts-for-gir, but just like the examples I have created for you, they use the workspace feature to make the locally created types known to the development environment. All these examples are using GJS in the last step and are working. So they actually show quite well what different setups could look like. If there are any examples missing here, I will be happy to add more, for example for Rollup and Turbopack.

What I could also add would be support for a declaration file that contains all generated types, so that only one entry in tsconfig.json is necessary, if that would still help.

By the way: For the future I plan to support JSR which is a TypeScript runtime independent package registry. So it is independent of Node.js and supports Deno, Bun, Node.js and any other JavaScript runtime environments, so I think it makes sense to publish packages for GJS there instead on npmjs.com.

I understand, however, that the long-term goal should be to be able to completely do away with Node.js, and that is also my long-term goal. In the long term, I would like to run ts-for-gir itself with GJS instead of Node.js. But at the same time I think that it doesn't hurt to have a package format with metadata and we can just use the metadata format of the package.json format, as this is widely used in the JavaScript universe anyway and is also supported by JSR and all bundlers I know, also esbuild has it's own package.json module resolution and is written in Go.

As far as I know, the GNOME Bundler is also working on TypeScript support. I still have to familiarise myself with this, but I am interested in how the types are handled there and to what extent we can work together here. Please don't get me wrong, if there really is a need for support without a package.json, I'll be happy to add it, but I'm not convinced yet.

@JumpLink
Copy link
Collaborator

JumpLink commented May 8, 2024

@vixalien Did my examples help you or do you think it would be better to read support without package.json?

@vixalien
Copy link
Author

Hello. I didn't take much time to examine the situation so forgive me if my responses are a bit shallow, but it seems the issue is that the new direction of the project is trying to work with other JS runtimes (Node, Bun, Deno, etc...) while kind of forgetting GJS. I say this because of the addition of package.json and moving to support registries npm/jsr which are not compatible with GJS.

With the current approach, ts-for-gir doesn't work with GJS, so we are still using outdated gi.ts. It would be nice to atleast have the old behavior of gi.ts and then maybe improve it from down the road.

As far as I know, the GNOME Bundler is also working on TypeScript support.

It's Workbench that's working on TypeScript support, and that actually requires projects like gi.ts and ts-for-gi, not the other way around.

By the way: For the future I plan to support JSR which is a TypeScript runtime independent package registry

Just so you know, this brings absolutely nothing to the table for GJS. GJS doesn't support package registries at all. Unless some work is done, jsr/node/cloudinary will almost mean nothing to GJS (unless you use BOTH Node and GJS, but that's another topic).

What I could also add would be support for a declaration file that contains all generated types, so that only one entry in tsconfig.json is necessary, if that would still help.

Yes. The package.json and all the additional files are really unused for GJS-based typescript solutions. All that's needed is that declaration file that links all generated types, like gi.d.ts. GJS can't do import Gtk from "@girs/gtk-4.0".

@JumpLink
Copy link
Collaborator

@vixalien Okay then I will try to implement it again to be independent of a package.json and a bundler. But I can't say just yet how quickly this will happen

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

No branches or pull requests

2 participants