bufbuild / protobuf-es

Protocol Buffers for ECMAScript. The only JavaScript Protobuf library that is fully-compliant with Protobuf conformance tests.
Apache License 2.0
1.11k stars 63 forks source link

When target is "ts" (TypeScirpt) the ".js" extension should not be added into import #203

Closed exocom closed 2 years ago

exocom commented 2 years ago
  - name: es
    out: src
    opt:
      - target=ts

Expected

import {GetAuditRequest, GetAuditResponse, ListAuditsRequest, ListAuditsResponse} from "./audit_pb";
import {MethodKind} from "@bufbuild/protobuf";

Got: .js at end of import line.

import {GetAuditRequest, GetAuditResponse, ListAuditsRequest, ListAuditsResponse} from "./audit_pb.js";
import {MethodKind} from "@bufbuild/protobuf";

Looked at making these changes, however, the deriveImportPath is used to determine imports. Making changes there affects all imports.

Was able to get the desired affect by changing the elToContent function. Passing in bool and then replace ".js" with "".

Example:

function elToContent(el: El[], importerPath: string, isTypeScript: boolean): string {
  const c: string[] = [];
  const symbolToIdentifier = processImports(
    el,
    importerPath,
    (typeOnly, from, names) => {
      if (isTypeScript) {
        from = from.replace(/.js/, "");
      }
      const p = names.map(({ name, alias }) =>
        alias == undefined ? name : `${name} as ${alias}`
      );
      const what = `{${p.join(", ")}}`;
      if (typeOnly) {
        c.push(`import type ${what} from ${literalString(from)};\n`);
      } else {
        c.push(`import ${what} from ${literalString(from)};\n`);
      }
    }
  );
  if (c.length > 0) {
    c.push("\n");
  }
  for (const e of el) {
    if (typeof e == "string") {
      c.push(e);
      continue;
    }
    const ident = symbolToIdentifier.get(e.id);
    if (ident != undefined) {
      c.push(ident);
    }
  }
  return c.join("");
}
smaye81 commented 2 years ago

Hey @exocom thanks for reaching out.

This is actually intentional behavior. Node.js has decided that file extensions are mandatory, and Microsoft has decided not to rewrite import extensions. That is why an import from "./foo.js" is the proper form in a TypeScript source file in a project with "type": "module", and we anticipate that it'll become the common form.

Consequently, I'll close this issue. But, just out of curiosity, what loader/bundler are you using? There are options to work around this issue depending on your setup.