i'm developing a vite plugin which transforms imported modules with custom extensions and turns them into javascript code which export some data (objects specifically).
everything is working fine when i test the plugin. but the problem is that when i use this plugin in a project (trying to simulate the developer experience with the plugin), the files with this custom extension is not recognized by typescript, which is expected of course, so i get this error Cannot find module './filename.someExtension' or its corresponding type declarations.
to keep things simple, i will put here some simple (and fake) examples of what i did, so that the question be clear.
say i have a file with json-like format containing a list of users, and the file has .users
extension.
as an example say this is the contents of the file:
[
{
name: "john",
age: 35,
job: "software engineer",
},
// other users
]
and the plugin code looks like this:
import { promises as fs } from "fs";
import type { Plugin } from "vite";
const UsersPlugin: () => Plugin = () => {
return {
name: "users-plugin",
enforce: "pre",
async load(id) {
if (id.endsWith(".users")) {
const src = await fs.readFile(id, "utf-8");
return { code: src };
}
return null;
},
async transform(src, id) {
if (id.endsWith(".users")) {
const users = JSON.parse(src)
const code = `
export users = ${users}
`
return {code};
}
return null;
},
};
};
export default UsersPlugin
and the developer (user of the plugin) would import the .users
file as follows
import {users} from '/path/to/file.users'
and here where the problem shows up.
the developer will see squiggly line under the '/path/to/file.users'
saying Cannot find module '/path/to/file.users' or its corresponding type declarations.ts(2307)
what i have tried is to create a users.d.ts
file in the root directory of my package so when the plugin is installed the users.d.ts
file will be located at node_modules/users.d.ts
the content of users.d.ts
:
declare module "*.users" {
interface User {
name: string;
age: number;
job: string;
}
const users: User[];
export { users };
}
this didn't work but if the developer (user of the plugin) puts this file somewhere in his project where it gets detected by typescript it works, or if he/she adds the path to the file in tsconfig.json
("include": ["node_modules/users-plugin/users.d.ts"]
) it also works.
i have also tried to add the file in package.json
of the package like this:
"types": "./lib/index.d.ts",
"exports": {
...
"./users": {
"types": "./users.d.ts"
},
...
},
"files": [
"lib/**/*",
"modules.d.ts"
],
(i saw something similar in the vite's code base itself for the client.d.ts file)
but it didn't work.
i tried also puting the users.d.ts
file under the lib
directory and add the /// <reference types="./users" />
tag at the top of index.d.ts
file, but none of these works.
what i want is, simply, when the user of my plugin installs the plugin from npm registry and adds it to his vite.config.ts
's plugins
list, the imports of files with .users
extension gets typed properly without the need of adding any extra config from the developer.
how can i achieve this ?