DanielXMoore / Civet

A TypeScript superset that favors more types and less typing
https://civet.dev
MIT License
1.56k stars 33 forks source link

JSONC/JSON5, yaml, toml ... #647

Open zolomatok opened 1 year ago

zolomatok commented 1 year ago

... you know where this is going 😄

Do you see a future where Civet might support the type-checked imports of "JSON with Comments" files, or maybe even YAML or TOML? Like how TS already supports direct, type-checked JSON imports.

I'm one of those peeps that are heartbroken, heartbroken I tell ya, by the fact that JSON can't have comments. VSCode has its own "JSON with Comments" format to make it not flip out over the comments, but those files fail at runtime in TS when imported. I'd use other data formats, but those can't be imported nicely.

... pwetty pwease?

STRd6 commented 1 year ago

Are there any links to issues in the TypeScript repo about this? Before implementing such a feature it is important for us to know where TS stands so we can ensure long term compatibility.

zolomatok commented 1 year ago

Good thinking, but I haven't found any mention of this in the roadmap.

There are two relevant entries in the Issues, this one, which requests support for JSON5 and this one, but that concerns itself with the format of specifically tsconfig.json and not anything else.

Neither have any satisfying resolution. The former is closed with a comment that I think is missing the point, the latter hasn't seem to have received any official response.

Bun purportedly have support for toml imports, but it doesn't really seem to work as stated in the docs. I played around with it and most I could do is import the toml file, but it's unknown. That does work and if you print it, you do see the parsed object tree. But since it's an unknown, you don't have autocomplete and type information, you don't have access to the properties like shown in the docs. At least not a way VSCode won't complain about.

For that to work, you need to create a .d.ts file, according to this discord thread. But I haven't tried that, cause I don't like polluting my project with .d.ts stuph.

STRd6 commented 1 year ago

Ok, after reading through the TS issues I think this is a good idea. Here's my thoughts:

I think this will strike a good balance between keeping the civet install small, keeping the config lookup/parsing quick, and allowing an intuitive flexibility of configuration.

STRd6 commented 1 year ago

For type-checked imports we may be able to auto-generate a .d.ts in the LSP in a similar way.

edemaine commented 1 year ago

This sounds great! I imagine this would need to be done in the LSP, the CLI, the unplugin, and civetsc (#61) once that exists? (In particular, this can't be done at the Civet transpilation level.) Not exactly easy, but I'd also love to have comments in JSON, and type checking sounds sweet too.

For typing, maybe we could use something like https://github.com/quicktype/quicktype if that's installed locally? Here's a little demo of quicktype from their website:

image

zolomatok commented 1 year ago

Allow for parsing different config file extensions based on what modules exist in the local user project

Are we talking about tsconfig here (or maybe 🐈.toml :))? Or just any json/yaml/toml file in the project?

To be honest, I'm not particularly concerned about the format of those particular config files, cause they are never(?) imported in the project and tsconfig at least already has comments. (Although I'm sure it would be nice for the Civet config file to have comments as well.)

What I'm really after is to be able to import any "jsonc"/yaml/toml file in a type-checked way. But I'm prolly misunderstanding what you mean by config files.

based on what modules exist in the local user project

I'm not sure about this. Seems kinda weird. I don't recall any other package where other installed packages modify the behaviour. I do appreciate the benefits of this, I'm just not a fond of this kind of implicit magic.

Come to think of it, pug has a feature where you can use installed jstransformers, but doing that feels like you're extending the features and this feels like you're modifying base functionality.

It's not like I have a better idea though, so I guess it's fine.

but I'd also love to have comments in JSON, and type checking sounds sweet too.

🫶

STRd6 commented 1 year ago
  • Allow for parsing different config file extensions based on what modules exist in the local user project

Some of my thoughts on this are combining with #641 so sorry for any confusion. Just trying to think through the general case of "what kind of data/config files can I import in my project" a subset of which is the civet config.

As for the magic lookups I think it would only really apply to the civet config part of this when no explicit config is specified. To opt out of the magic behavior just specify an explicit config.

When importing .json/.yml in your actual .civet files the explicit extension would prevent any mysterious behavior. If there is no yml module installed then we can't really add any type info to imported .yml files and I don't want to include node bindings for every common data file in the core Civet package. If there is a yml module installed odds are it's the same one that the project is using so using it, if available, to generate type info for the LSP sounds 👍

Thanks for opening the issue and I hope this clarifies things!

zolomatok commented 1 year ago

Sure, right, gotcha! No probs!

zolomatok commented 3 weeks ago

For anyone looking for this, if you're using Bun, importing a JSON with comments does work.

  1. If using VSC, have this in your VSC user/workspace settings to make it shush about having comments in a regular JSON file:
    "files.associations": {
    "*.json": "jsonc"
    },
  2. Just have a plain something.json file (So not jsonc or json5. Apparently jsonc works as well, but VSC couldn't stop complaining about the import. Running the file might have been fine, but I needed VSC to be happy.)
  3. Feel free to have comments in it
  4. Import with import something from './something.json' with { type: 'text' }
  5. You'll have proper type info on something