i18next / i18next-parser

Parse your code to extract translation keys/values and manage your catalog files
MIT License
488 stars 199 forks source link

[7.6.0] types not importable #774

Closed Cielquan closed 1 year ago

Cielquan commented 1 year ago

🐛 Bug Report

With #660 (release 7.0.0) a type definition file was added and with #694 (release 7.5.0) the file was added to the dist when building. Prior it was missing in the npm package.

I just updated to 7.6.0 and can verify that the types are installed in node_modules/i18next-parser/dist/index.d.ts. Unfortunately I cannot import them with import { UserConfig } from "i18next-parser"; inside i18next-parser.config.ts. I get the error that the file cannot be found.

I looked in some other packages installed in my node_modules and in most cases I can find a index.d.ts file in the package's root directory and not their dist directory. When I move the index.d.ts file of i18next-parser one directory up in it's root, I can import it with no issues.

I have 0 knowledge about packaging in the JS world, so I cannot comprehend where the real underlying issue is. Maybe I am just too unknowing in this department to correctly import them. But because all those other packages had their types in their root directory I think that's the way to go?

To Reproduce

  1. Install i18next-parser
  2. create i18next-parser.config.ts file
  3. add import { UserConfig } from "i18next-parser";
  4. see error

Expected behavior

The types should be importable without tinkering.

Your Environment

Additional Information

I also had the import issue when I build my custom lexer (#678) to support shouldUnescape. I could not import the JsxLexer class and simply extend it. So I had to fully copy paste the BaseLexer, JavascriptLexer and JsxLexer source to add a couple lines of code.

Like stated above I don't know anything about packaging, but e.g. i18next-conv (repo) has a cli and I can import it to build custom scripts. They have a file in the bin/ directory and their source in a lib/ instead of dist/ directory and then export everything from a index.js file in the package root. Maybe this would be a solution here too?

EDIT: add additional info EDIT2: add additional info EDIT3: add additional info

peksipatongeis commented 1 year ago

package.json is missing the types property and it fails because the types were moved to the dist folder. Created a PR to add the missing types property to fix this.

peksipatongeis commented 1 year ago

Meanwhile I fixed the issue by creating a local type declaration i18next-parser.d.ts, just make sure it gets included by your tsconfig

declare module 'i18next-parser' {
  import EventEmitter from 'events';

  export type SupportedLexer = 'HandlebarsLexer' | 'HTMLLexer' | 'JavascriptLexer' | 'JsxLexer' | 'VueLexer';

  // BaseLexer is not importable therefore this is the best if done simple
  export class CustomLexerClass extends EventEmitter {}
  export type CustomLexer = typeof CustomLexerClass;

  export interface CustomLexerConfig extends Record<string, unknown> {
    lexer: CustomLexer;
  }

  export interface HandlebarsLexerConfig {
    lexer: 'HandlebarsLexer';
    functions?: string[];
  }

  export interface HTMLLexerConfig {
    lexer: 'HTMLLexer';
    functions?: string[];
    attr?: string;
    optionAttr?: string;
  }

  export interface JavascriptLexerConfig {
    lexer: 'JavascriptLexer';
    functions?: string[];
    namespaceFunctions?: string[];
    attr?: string;
    parseGenerics?: false;
    typeMap?: Record<string, unknown>;
  }

  export interface JavascriptWithTypesLexerConfig {
    lexer: 'JavascriptLexer';
    functions?: string[];
    namespaceFunctions?: string[];
    attr?: string;
    parseGenerics: true;
    typeMap: Record<string, unknown>;
  }

  export interface JsxLexerConfig {
    lexer: 'JsxLexer';
    functions?: string[];
    namespaceFunctions?: string[];
    attr?: string;
    transSupportBasicHtmlNodes?: boolean;
    transKeepBasicHtmlNodesFor?: string[];
    parseGenerics?: false;
    typeMap?: Record<string, unknown>;
  }

  export interface JsxWithTypesLexerConfig {
    lexer: 'JsxLexer';
    functions?: string[];
    namespaceFunctions?: string[];
    attr?: string;
    transSupportBasicHtmlNodes?: boolean;
    transKeepBasicHtmlNodesFor?: string[];
    parseGenerics: true;
    typeMap: Record<string, unknown>;
  }

  export interface VueLexerConfig {
    lexer: 'VueLexer';
    functions?: string[];
  }

  export type LexerConfig =
    | HandlebarsLexerConfig
    | HTMLLexerConfig
    | JavascriptLexerConfig
    | JavascriptWithTypesLexerConfig
    | JsxLexerConfig
    | JsxWithTypesLexerConfig
    | VueLexerConfig
    | CustomLexerConfig;

  export interface UserConfig {
    contextSeparator?: string;
    createOldCatalogs?: boolean;
    defaultNamespace?: string;
    defaultValue?: string | ((locale?: string, namespace?: string, key?: string) => string);
    indentation?: number;
    keepRemoved?: boolean;
    keySeparator?: string | false;
    lexers?: {
      hbs?: (SupportedLexer | CustomLexer | LexerConfig)[];
      handlebars?: (SupportedLexer | CustomLexer | LexerConfig)[];
      htm?: (SupportedLexer | CustomLexer | LexerConfig)[];
      html?: (SupportedLexer | CustomLexer | LexerConfig)[];
      mjs?: (SupportedLexer | CustomLexer | LexerConfig)[];
      js?: (SupportedLexer | CustomLexer | LexerConfig)[];
      ts?: (SupportedLexer | CustomLexer | LexerConfig)[];
      jsx?: (SupportedLexer | CustomLexer | LexerConfig)[];
      tsx?: (SupportedLexer | CustomLexer | LexerConfig)[];
      default?: (SupportedLexer | CustomLexer | LexerConfig)[];
    };
    lineEnding?: 'auto' | 'crlf' | '\r\n' | 'cr' | '\r' | 'lf' | '\n';
    locales?: string[];
    namespaceSeparator?: string | false;
    output?: string;
    pluralSeparator?: string;
    input?: string | string[];
    sort?: boolean | ((a: string, b: string) => -1 | 0 | 1);
    skipDefaultValues?: boolean | ((locale?: string, namespace?: string) => boolean);
    useKeysAsDefaultValue?: boolean | ((locale?: string, namespace?: string) => boolean);
    verbose?: boolean;
    failOnWarnings?: boolean;
    failOnUpdate?: boolean;
    customValueTemplate?: Record<string, string> | null;
    resetDefaultValueLocale?: string | null;
    i18nextOptions?: Record<string, unknown> | null;
    yamlOptions?: Record<string, unknown> | null;
  }
}
Cielquan commented 1 year ago

Thanks for the idea. I already have a local type declaration file. The file included in i18next-parser is originally made by me (#660).

I wanted to remove the local file to reduce the file count, but after your PR is merged and released I will be able to do that. Thanks again for your fix.

karellm commented 1 year ago

Should be fixed as of 7.7.0

Cielquan commented 1 year ago

I just updated to 7.7 and can confirm that the issue is solved.

landabaso commented 9 months ago

Isn't it missing declarations for parser, gulp, broccoli and transform? I was trying to use i18next-parser as an API using typescript and it won't let you import any of those because declarations are missing.