denoland / dnt

Deno to npm package build tool.
MIT License
1.21k stars 38 forks source link

Force export as a type export to replace a namespace usage. #209

Open UrielCh opened 2 years ago

UrielCh commented 2 years ago

Hi,

I almost port ChromeDevToolsProtocol project to deno, I'm facing an last error.

Original version

My ChromeDevToolsProtocol api use to contains a big protocol.d.ts file like this:

export namespace Protocol {
    export namespace Accessibility {
      export interface ....
    }
}

exported in mod.ts with:

export { Protocol } from "./types/protocol.d.ts";

full file

as mention in Deno FAQS

  • Only declare namespace is supported. Runtime namespace is legacy TypeScript syntax that is not supported.

Fixed version

So to clean that, I replace all those namespace by modules

in protocol.d.ts :

export * as Accessibility from './accessibility.d.ts'

exported in mod.ts with:

export * as Protocol from "./types/protocol.d.ts";

full version

With that change my deno code works fine.

But once converted to nodeJS with dnt, this export is generated as a code export, event if it only contains interfaces. (I also replace interface by type) so it only contains type.

The dnt conversion end with an error:

Error: Cannot find module './types/protocol' 
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:1005:19) {
  code: 'MODULE_NOT_FOUND',
}

The line causing the error in the generate node code is:

 exports.Protocol = __importStar(require("./types/protocol"));

yep, the is no code for protocol, it's only a definition file.

To fix that I should replace: export * as Protocol from "./types/protocol.d.ts"; by something like that: export type * as Protocol from "./types/protocol.d.ts"; but this syntax is not valid in Typescript.

What did I do wrong ? how can I force this export * as to be a type.

Thx for your time, deno is great.

UrielCh commented 2 years ago

I found an ugly solution:

I replace my non working code

export type * as Protocol from "./types/protocol.d.ts";

by an ugly version that looks to works

export { type Protocol } from "./lib/protocolModule.ts";

and add a file lib/protocolModule.ts:

export * as Protocol from "../types/protocol.d.ts";

Is that the proper solution ?

UrielCh commented 2 years ago

After publishing this version, my types/*.d.ts are not available in my nodejs version. I need to add an extra step to copy and convert d.ts file in the build.ts,.

  Deno.mkdirSync("npm/types/types");
  const files = Deno.readDirSync("types");
  for (const file of files) {
    if (!file.isFile)
      continue;
    let text = Deno.readTextFileSync(`types/${file.name}`)
    text = text.replace(/.d.ts(["'])/g, "$1");
    Deno.writeTextFileSync(`npm/types/types/${file.name}`, text);
  }

Is there a proper call in dnt to copy and convert a d.ts file from deno to node (In my case removing all the d.ts at the end the import statement)