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

Can't make it work with Vite/Svelte #812

Closed
howesteve opened this issue Sep 12, 2023 · 31 comments
Closed

Can't make it work with Vite/Svelte #812

howesteve opened this issue Sep 12, 2023 · 31 comments
Assignees
Labels
enhancement New feature or request hacktoberfest help wanted Extra attention is needed question Further information is requested

Comments

@howesteve
Copy link

howesteve commented Sep 12, 2023

Hello. I'd love to test this, but I just can't make it work with Vite. Tried for days, and nothing. It always throws:

module.ts:653 Uncaught Error: Error on typia.is(): no transform has been configured. Read and follow https://typia.io/docs/setup please

I followed the setup guide, tried the npx typia setup method, the manual installation, and no deal.

I've created my test repo using these steps:

pnpm create vite@latest vite-svelte  # then:  Svelte > Typescript
cd vite-svelte
pnpm i -D typia
pnpm i -D rollup-plugin-typescript2 typescript tslib
npx typia setup # then: pnpm > tsconfig.json
pnpm run dev

I checked, and the transformer plugin is in place:

 "plugins": [
      {
        "transform": "typia/lib/transform"
      }
    ],

Until here, project loads normally. Then when I edit App.svelte to include:

  import typia, { tags } from "typia";

  const matched: boolean = typia.is<IMember>({
    email: "[email protected]",
    age: 30,
  });

  console.log(matched); // true

  interface IMember {
    email: string & tags.Format<"email">;
    age: number &
      tags.Type<"uint32"> &
      tags.ExclusiveMinimum<19> &
      tags.Maximum<100>;
  }

and as I save, immediately, the error above is thrown.

I've uploaded my repository into here:
https://github.com/howesteve/typia-test/

Any clues? Is there any bare-bones repository of this actually running with vite?

Thanks.

@matthew-dean
Copy link

Did you follow this guide? https://typia.io/docs/setup/#vite

@howesteve
Copy link
Author

Yes I did. That's what I meant when I wrote this:

I followed the setup guide, tried the npx typia setup method, the manual installation, and no deal.

@tsengia
Copy link
Contributor

tsengia commented Sep 16, 2023

I am also seeing similar problems. I am using vite version: vite/4.4.8 win32-x64 node-v18.12.0 and yarn version 3.6.1

@tsengia
Copy link
Contributor

tsengia commented Sep 21, 2023

I think I may have found the source of the problem:

} else if (file.substring(file.length - 3) === ".ts")

Because your file ends with .svelte and not .ts, the TypiaProgrammer never includes your file during the gather() phase of transformation.

@tsengia
Copy link
Contributor

tsengia commented Sep 21, 2023

@matthew-dean Could you give PR #816 a try? It's a very simple fix. I did a quick and dirty test on my own machine and it seemed to work, but I am using React and not Svelte...

@samchon samchon self-assigned this Sep 21, 2023
@samchon samchon added the enhancement New feature or request label Sep 21, 2023
@samchon
Copy link
Owner

samchon commented Sep 21, 2023

@howesteve @tsengia Will you svelte generation with typia@next package?

As I don't know svelte at all, cannot sure it to work.

npm install --save typia@next

@samchon
Copy link
Owner

samchon commented Sep 21, 2023

Tried but not working on *.svelte file. TypeScript compiler can't detect it.

@samchon samchon added help wanted Extra attention is needed question Further information is requested labels Sep 21, 2023
@tsengia
Copy link
Contributor

tsengia commented Sep 28, 2023

@samchon Even with latest fix still can't get it to work with react.

I had to modify/hot patch rollup-plugin-typescript2 to support "allowImportingTsExtensions": true due to it defaulting to "noEmit": true, but even with that hot patch I'm still not 100% of the way there. Typia transforms 2 modules but then rollup errors out with:

[rpt2] src/main.tsx:1:10 - error TS2614: Module '"react/jsx-runtime"' has no exported member 'jsx'. Did you mean to use 'import jsx from "react/jsx-runtime"' instead?

 import { jsx } from "react/jsx-runtime";
           ~~~
src/main.tsx:6:21 - error TS2345: Argument of type 'HTMLElement | null' is not assignable to parameter of type 'Element | DocumentFragment'.
  Type 'null' is not assignable to type 'Element | DocumentFragment'.

 ReactDOM.createRoot(document.getElementById("root")).render(

I have a hunch that maybe toying with the Vite plugin settings may fix this, possibly by changing the plugin ordering.

On another note, generation with .tsx files now works. Sadly, I'm struggling to fit this generation step into the build process due to the regular tsconfig.json including src/, but then requiring the build to utilize the generated code from generated/ and not from src/. It's almost as if I need two tsconfig.json files: one for generation and one for post-generation build.

@tsengia
Copy link
Contributor

tsengia commented Sep 28, 2023

Update:
Changing Vite's plugin ordering did me no good, however I did find a different "solution".

Essentially, I had to cut Vite and the @vite-plugin/react out of the picture and use only rollup-plugin-typescript2 and the tspCompiler from ts-patch, as well as disabling Vite's esbuild. The final result of my vite.tsconfig.ts is below:

import { defineConfig } from "vite";
import typescript from "rollup-plugin-typescript2";
import tspCompiler from "ts-patch/compiler";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [{...typescript({
    typescript: tspCompiler,
    sourceMap: true,
    inlineSources: true
  }), enforce:"post"}],
  esbuild: false,
  // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
  //
  // 1. prevent vite from obscuring rust errors
  clearScreen: false,
  // 2. tauri expects a fixed port, fail if that port is not available
  server: {
    port: 1420,
    strictPort: true,
  },
  // 3. to make use of `TAURI_DEBUG` and other env variables
  // https://tauri.studio/v1/api/config#buildconfig.beforedevcommand
  envPrefix: ["VITE_", "TAURI_"],
});

Additionally, my tsconfig.json file looks as such:

  "compilerOptions": {
    "target": "ES2020",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsxdev",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,

    /* Needed for mobx */
    "useDefineForClassFields": true,

    /* Needed for typia */
    "plugins": [
      { "transform": "typia/lib/transform" }
    ]
  },

Note: Please ignore the clearScreen, server, and envPrefix fields above, they are artifacts from Tauri's build settings and aren't necessary for Typia.

With these settings, I was able to get my React app to be transformed + transpiled to JavaScript, however the resulting .js file was not minified. There is probably additional settings that I need to tweak to get the minified output, but I am excited to see that the Typia transforms were applied.

One good thing about using the tspCompiler instead of ts-patch install is that it sidesteps the fact that ts-patch is broken for Yarn v3 (Berry) PnP mode due to how it "persistently installs" itself by patching the typescript compiler source in node_modules. Using tspCompiler sidesteps this entirely and allows you to use ts-patch regardless of your package manager, which is pretty nice.

@spencerkohan
Copy link

I'm also facing this issue, with Vite's react template.

I face this error when trying to start the dev server:

% yarn dev
yarn run v1.22.19
$ vite
error when starting dev server:
Error: error TS5096: Option 'allowImportingTsExtensions' can only be used when either 'noEmit' or 'emitDeclarationOnly' is set.

My tsconfig looks like this:

{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": [
      "ES2020",
      "DOM",
      "DOM.Iterable"
    ],
    "module": "ESNext",
    "skipLibCheck": true,
    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "plugins": [
      {
        "transform": "typia/lib/transform"
      }
    ],
    "strictNullChecks": true
  },
  "include": [
    "src"
  ],
  "references": [
    {
      "path": "./tsconfig.node.json"
    }
  ]
}

And my vite config is the same as what's used in the documentation:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

import typescript from "rollup-plugin-typescript2";

// https://vitejs.dev/config/
export default defineConfig({
  esbuild: false,
  plugins: [
    typescript(),
    react(),
  ],
  server: {
    port: 3000
  }
})

The issue seems to be caused by rollup-plugin-typescript which forces certain tsconfig parameters:

noEmit: false (Rollup controls emit)

This seems to make it virtually impossible to use with the react vite plugin, because the noEmit option forces you to disable the allowImportingTsExtensions option, which breaks compilation of tsx files with this error:

[plugin:rpt2] src/main.tsx:1:10 - error TS2305: Module '"react/jsx-dev-runtime"' has no exported member 'jsxDEV'.

1 import { jsxDEV } from "react/jsx-dev-runtime";
           ~~~~~~
src/main.tsx:4:17 - error TS5097: An import path can only end with a '.tsx' extension when 'allowImportingTsExtensions' is enabled.

4 import App from "./App.tsx";

@tsengia
Copy link
Contributor

tsengia commented Nov 5, 2023

The issue seems to be caused by rollup-plugin-typescript which forces certain tsconfig parameters:

noEmit: false (Rollup controls emit)

This seems to make it virtually impossible to use with the react vite plugin, because the noEmit option forces you to disable the allowImportingTsExtensions option, which breaks compilation of tsx files with this error:

I forgot to mention, when I got Typia to work in my above comment, I had to modify the rollup-plugin-typescript2 plugin to allow for the noEmit option.

@spencerkohan
Copy link

@tsengia how did you do this? did you modify the source or how else did you achieve it?

@a-kla
Copy link

a-kla commented Nov 10, 2023

I use Typia with SvelteKit (+ MDsveX) and din't need to modify any code.

My vite.config.ts is like the Docs says:

import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
import typescript from "rollup-plugin-typescript2" // @rollup/plugin-typescript";

export default defineConfig({
	esbuild: false,
	plugins: [ sveltekit(), typescript()]
});

Typia is not working inside *.svelte files. But on *.ts files that can be imported.

My Workaround looks like this:

// Example.ts
import typia, { tags } from "typia";

export type Example = {
	Id: string & tags.MinLength<12>;
	Date: string & tags.Format<"date">;
	editable: boolean;
}

export const ExampleToJson = typia.json.createAssertStringify<Example>();
export const ExampleFromJson = typia.json.createAssertParse<Example>();
export const ExampleWithRandomData: Example = typia.random<Example>();
<script lang="ts">
	import type { Example } from '$lib/Example';
	import { ExampleToJson, ExampleWithRandomData } from '$lib/Example';

	let example: Example = ExampleWithRandomData;
	let json = '';

	try {
		json = ExampleToJson(example);
	} catch (error) {
		console.error(error);
	}
	console.log(example);
</script>

{json}

Only that Typia isn't type-safe if i use it with classes (see #683 ) causes me headaches.

@MarArMar
Copy link
Contributor

Experiencing this problem too.

Would love to use typia for svelte but I spent 30 minutes & still can't make it work so will wait for V5.

@MarArMar
Copy link
Contributor

MarArMar commented Nov 11, 2023

Note : on a new Sveltekit deployment,

I had to pass in the check: false arguments in vite.config.ts to stop the rollup plugin blocking the dev

typescript({ check: false }),

As it was raising a crazy amount of errors

It worked on Typescript files in the svelte repo so Typia can be used with sveltekit

BUT I then tried on a Turborepo and it did not work for other workspaces TS files (issue submitted here: ezolenko/rollup-plugin-typescript2#465)

@a-kla
Copy link

a-kla commented Nov 12, 2023

@MarArMar Do you need pnpm-workspaces? Without it I can use TS.
This seems to be a Bug in Vite: vitejs/vite#5370

Try this:
Move /packages/common/lib/log-ts.ts to apps/SKImportTS/src/lib/log-ts.ts
and use import { log, messageLoaded } from "$lib/log-ts" // was "common/lib/log-ts";

And I don't need check: false but "sourceMap": false, in tsconfig.json to suppress all […] .ts" points to missing source files' messages. The funny thing is that the Source-Maps are still there and working.

@MarArMar
Copy link
Contributor

MarArMar commented Nov 17, 2023

Ok here is a working example : Turborepo X Sveltekit X Typia

MarArMar/TurboTestBis

Main thing was the vite config :

import { sveltekit } from "@sveltejs/kit/vite";
import { defineConfig } from "vite";
import typescript from "rollup-plugin-typescript2";

export default defineConfig({
  // esbuild: false,
  plugins: [
    sveltekit(),
    typescript({
      check: false,
    }),
  ],
});

Have to not set esbuild: false else loading of workspace modules in ts do not work

Sidenote : I tested using typia in modules outside svelte imported in svelte, not sure it works within svelte files, but was good enough for me to be able to make wrappers outside of svelte & import them

@MarArMar
Copy link
Contributor

MarArMar commented Nov 22, 2023

@a-kla Unfortunaltely it didn't work for me :

in vite.config.ts :

export default defineConfig({
  // esbuild: false,
  plugins: [
    sveltekit(),
    typescript({
      // check: false,
      sourceMap: false,
    }),
  ],
});

Makes the page a 500 error,

If I do :

export default defineConfig({
  // esbuild: false,
  plugins: [
    sveltekit(),
    typescript({
      check: false,
      sourceMap: false,
    }),
  ],
});

I can see the page but Typia seems to be not working when imported from a ts file :

"true (expected: true) & notMatched is true (expected: false)"

It does not change anything if I add in tsconfig.json :

{
  "compilerOptions": {
    "sourceMap": false,
    "checkJs": false,
  }
}

Finally if I add the "esbuild: false," in vite.config.ts, I cannot import ts files from other modules in the workspace (deal-breaker for a monorepo)

My repo : https://github.com/MarArMar/TurboSvelteKitTypia

@MarArMar
Copy link
Contributor

MarArMar commented Nov 22, 2023

I had to modify/hot patch rollup-plugin-typescript2 to support "allowImportingTsExtensions": true due to it defaulting to "noEmit": true, but even with that hot patch I'm still not 100% of the way there. Typia transforms 2 modules but then rollup errors out with:

I am desperatly trying to make this work : https://github.com/MarArMar/TurboSvelteKitTypia

How did you manage to modify/hot patch the rollup-plugin-typescript2 ? Is your patch live in typia ?

Update : Actually it might not be that at all, my problem is with importing ts files, not tsx files..

@tsengia
Copy link
Contributor

tsengia commented Nov 23, 2023

I had to modify/hot patch rollup-plugin-typescript2 to support "allowImportingTsExtensions": true due to it defaulting to "noEmit": true, but even with that hot patch I'm still not 100% of the way there. Typia transforms 2 modules but then rollup errors out with:

I am desperatly trying to make this work : https://github.com/MarArMar/TurboSvelteKitTypia

How did you manage to modify/hot patch the rollup-plugin-typescript2 ? Is your patch live in typia ?

Update : Actually it might not be that at all, my problem is with importing ts files, not tsx files..

My patch is not in Typia; it was a local patch I did to rollup-plugin-typescript2 while experimenting with fixing the issue.

I believe the patch involved modifying this function so that when allowImportingTsExtensions is set to true, then noEmit also gets set to true.

Currently, rollup-plugin-typescript2 always has noEmit set to false, regardless of allowImportingTsExtensions.
If I recall correctly, my patch amounted to: if (allowImportingTsExtenions) { noEmit = true; } (note that this is pseudo code, but I hope it illustrates my point).

Later next week I'll be able to dig through my files again to get you an absolute answer, but right now I'm away from the PC that I used to perform this patch so I don't have the exact code I used on hand.

@a-kla
Copy link

a-kla commented Nov 23, 2023

@a-kla Unfortunaltely it didn't work for me :

in vite.config.ts :

export default defineConfig({
  // esbuild: false,
  plugins: [
    sveltekit(),
    typescript({
      // check: false,
      sourceMap: false,
    }),
  ],
});

I found out that this works well in my Project:

/// <reference types="@sveltejs/kit" />

import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vitest/config';

// for Typia
import typescript from "rollup-plugin-typescript2"

export default defineConfig({
	plugins: [
		{
			enforce: 'pre', // <= this line fixes all my initial problems
			...typescript(),
		},
		sveltekit(),
	],
});

Now I have no changes in my tsconfig.json, except the one the Setup Wizard added automatically.

! Important Note:
It seems that I don't get any Warnings from Typia/rollup-plugin-typescript2.
If I see no transform has been configured. - Errors it just means that I did something wrong (used Date for Protobuf) and no transform *could made*. . If I test the code on https://typia.io/playground/ I see what's wrong.

@MarArMar
Copy link
Contributor

@a-kla Thank you so much for your answer !

managed to finally make it work with this in vite.config.ts :

" include: ["../../**/*.ts+(|x)"],"

@null-prophet
Copy link

I'm using an ESM package and no matter how I tried this, even using the overrides for the tsconfig it would just break subsequent code.

The easiest way is to add in a generate function you trigger manually (yarn generate) or similar, tie that into your build phase too.

Then have all your code point to that registered code. (don't forget to get eslint to forget about it too if its in your src folder) and it will work.

# trconfig-base.json
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "compilerOptions": {
    "allowJs": false,
    "allowSyntheticDefaultImports": true,
    "allowUnreachableCode": false,
    "allowUnusedLabels": false,
    "declaration": true,
    "emitDeclarationOnly": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "noFallthroughCasesInSwitch": true,
    "noImplicitAny": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "removeComments": false,
    "resolveJsonModule": true,
    "skipDefaultLibCheck": true,
    "sourceMap": true,
    "strictFunctionTypes": true,
    "strictNullChecks": true,
    "stripInternal": true,
    "allowImportingTsExtensions": true,
    "baseUrl": "."
  }
}

#tsconfig.json
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "extends": "./tsconfig-base.json",
  "compilerOptions": {
    "lib": ["ESNext"],
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "target": "ESNext",
    "baseUrl": ".",
    "esModuleInterop": true,
    "paths": {
      "@api/*": ["src/*"]
    },
    "plugins": [
      {
        "transform": "typia/lib/transform"
      }
    ],
    "strictNullChecks": true,
    "strict": true
  },
  "exclude": ["node_modules", ".build"]
}


# package.json (pertinent parts)

"type": "module",
  "scripts": {
    "format": "prettier --write .",
    "lint": "eslint --cache . --ext ts,tsx",
    "prebuild": "rimraf .build/ && yarn generate",
    "build": "yarn generate && node -r dotenv/config --import tsx esbuild.config.js",
    "prepare": "ts-patch install && typia patch && husky install",
    "generate": "typia generate --input src/typia/ts --output src/typia --project tsconfig.json",
    "postinstall": "husky install",
    "start": "tsx src/index.ts",
    "start:watch": "tsx watch src/index.ts",
    "start:debug": "node --inspect --import tsx 'src/index.ts'",
    "test": "vitest run --coverage",
    "test:watch": "vitest",
    "upgrade-all": "yarn-upgrade-all"
  },

# vitest.config.mts
import { defineConfig } from 'vitest/config'
import tsconfigPaths from 'vite-tsconfig-paths'

export default defineConfig({
  plugins: [tsconfigPaths()],
  test: {
    // ... Specify options here.
    dir: './src',
    setupFiles: ['./test/global-setup.ts'],
    coverage: {
      include: ['src/**/*.ts'],
    },
  },
})

# esbuild.config.js
import esbuild from 'esbuild'

esbuild.buildSync({
  entryPoints: ['./src/'],
  bundle: true,
  minify: true,
  sourcemap: true,
  format: 'esm',
  outfile: '.build/index.mjs',
  platform: 'node',
  external: ['node'],
  target: ['node18'],
  banner: {
    js: "import { createRequire } from 'module'; const require = createRequire(import.meta.url);",
  },
  // external: ['react', 'react-dom', 'ejs', 'express'],
})

This works well. You still get the decorator creation in tsc which isn't really needed right now but the generate works well and now have no issues with all the weirdness you get with vitest and esbuild getting in the way.

@samchon
Copy link
Owner

samchon commented Dec 30, 2023

If some of you have knowhow about this issue, please send a website PR please.

@MarArMar
Copy link
Contributor

MarArMar commented Apr 27, 2024

If you also experience "TypeError: Cannot read properties of undefined (reading 'add')" for using typia with vite & rollup-plugin-typescript2,

I have this issue opened :
ezolenko/rollup-plugin-typescript2#470

With a reproduction repo for those who might have fixed the problem already :
https://github.com/MarArMar/Sveltekit-RPT2-Typia

Will update on fix & welcoming help

@ryoppippi
Copy link
Contributor

ryoppippi commented Jun 1, 2024

Hi
I made a bundler plugin using unplugin

https://github.com/ryoppippi/unplugin-typia/tree/main/packages/unplugin-typia

@MarArMar
You can try it! it works fine with sveltekit
https://github.com/ryoppippi/unplugin-typia/tree/main/examples/sveltekit

@MarArMar
Copy link
Contributor

MarArMar commented Jun 2, 2024

Will try and give feedback probably next week, thanks so much @ryoppippi !! 😀

@ryoppippi
Copy link
Contributor

ryoppippi commented Jun 8, 2024

@MarArMar
Thanks!
We added the setup instruction to the official docs!
Check this out and plz give us a feedback!

https://typia.io/docs/setup/#unplugin-typia

@ryoppippi
Copy link
Contributor

ryoppippi commented Jun 18, 2024

@samchon
We can close this issue.
If unplugin-typia does not work for Sveltekit, open an issue for https://github.com/ryoppippi/unplugin-typia/

@MarArMar
Copy link
Contributor

@ryoppippi thanks for the script !!! Could not manage to use typia correctly before,

I got it to work correctly in a monorepo, also with sourcemaps, meaning the browser & server debugger also functions correctly ✅

@ryoppippi
Copy link
Contributor

@MarArMar
Brilliant!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request hacktoberfest help wanted Extra attention is needed question Further information is requested
Projects
None yet
Development

No branches or pull requests

9 participants