@wolfstar/i18next-type-generator 3.1.1 → 3.1.2-next-20260907104340

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -168,7 +168,7 @@ const main = defineCommand({
168
168
  },
169
169
  async run({ args }) {
170
170
  await generate([args.source, args.destination], {
171
- verbose: args.verbose,
171
+ verbose: args.verbose ?? false,
172
172
  oxfmt: args.oxfmt,
173
173
  prettier: args.prettier,
174
174
  indentation: parseIndentation(args.indentation)
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","names":[],"sources":["../src/generate.ts","../src/cli.ts"],"sourcesContent":["import { gray, green, italic, yellow } from 'colorette';\nimport { mkdir, opendir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname, join, resolve } from 'node:path';\nimport { inspect } from 'node:util';\n\nconst ci = 'CI' in process.env && process.env.CI !== 'false';\n\nconst FileIcon = ci ? '📄' : '\\uE628';\nconst DirectoryIcon = ci ? '📂' : '\\uF413';\n\nconst GENERATED_FILE_HEADER = ['// This file is automatically generated, do not edit it.', '/* eslint-disable */', '/* oxlint-disable */'] as const;\n\nconst FORMATTER_IGNORE = ['// oxfmt-ignore', '// prettier-ignore'] as const;\n\n/**\n * Inject formatter and linter ignore directives into the already-formatted output.\n *\n * The file-level `eslint-disable` / `oxlint-disable` comments suppress all lint rules, while the\n * per-statement `oxfmt-ignore` / `prettier-ignore` comments protect the two top-level statements\n * (the `i18next` import and the `declare module` block), since neither formatter supports a\n * whole-file inline ignore.\n * @param source The formatted generated source.\n */\nexport function annotateGeneratedFile(source: string): string {\n\tconst ignore = FORMATTER_IGNORE.join('\\n');\n\tconst annotated = source\n\t\t.replace(/^(import\\s+['\"]i18next['\"])/m, `${ignore}\\n$1`)\n\t\t.replace(/^(declare\\s+module\\s+['\"]i18next['\"])/m, `${ignore}\\n$1`);\n\n\treturn `${GENERATED_FILE_HEADER.join('\\n')}\\n${annotated}`;\n}\n\n/**\n * Recursively walk through the directory and generate the types.\n * @param path The path to walk through.\n * @param namespace The namespace to use.\n */\nasync function recurse(lines: string[], path: string, namespace: string, options: GenerateOptions) {\n\tconst indent = options.indentation.repeat(3);\n\n\tif (options.verbose) console.log(gray(`Reading directory ${DirectoryIcon} ${green(path)}...`));\n\n\tconst entries = [];\n\tfor await (const dirent of await opendir(path)) {\n\t\tentries.push(dirent);\n\t}\n\tentries.sort((a, b) => a.name.localeCompare(b.name));\n\n\tfor (const dirent of entries) {\n\t\tconst file = join(path, dirent.name);\n\t\tif (dirent.isFile()) {\n\t\t\tif (!dirent.name.endsWith('.json')) continue;\n\t\t\tif (options.verbose) console.log(gray(`Processing ${FileIcon} ${green(file)}...`));\n\n\t\t\tconst name = dirent.name.slice(0, -5);\n\t\t\tconst key = JSON.stringify(namespace ? `${namespace}/${name}` : name);\n\t\t\tconst data = JSON.stringify(JSON.parse(await readFile(file, 'utf8')), undefined, options.indentation);\n\t\t\tlines.push(`${indent}${key}: ${data.replaceAll('\\n', `\\n${indent}`)};`);\n\t\t} else if (dirent.isDirectory()) {\n\t\t\tawait recurse(lines, file, namespace ? `${namespace}/${dirent.name}` : dirent.name, options);\n\t\t}\n\t}\n}\n\nasync function formatWithOxfmt(source: string, destination: string, options: GenerateOptions): Promise<string | undefined> {\n\tif (!options.oxfmt) return;\n\n\ttry {\n\t\tif (options.verbose) console.log(gray('Loading oxfmt...'));\n\n\t\tconst { format } = await import('oxfmt');\n\t\tconst { code, errors } = await format(destination, source);\n\t\tif (errors.length > 0) {\n\t\t\tthrow new Error(errors.map((error) => error.message).join('\\n'));\n\t\t}\n\n\t\tif (options.verbose) console.log(gray('Formatting with oxfmt.'));\n\n\t\treturn code;\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tconsole.warn(\n\t\t\tyellow(\n\t\t\t\toptions.verbose\n\t\t\t\t\t? `Failed to format with oxfmt: ${message}. Continuing with unformatted output.`\n\t\t\t\t\t: 'Failed to format with oxfmt; install it as a dependency or use --no-oxfmt. Continuing with unformatted output.'\n\t\t\t)\n\t\t);\n\t}\n\n\treturn undefined;\n}\n\nasync function formatWithPrettier(source: string, destination: string, options: GenerateOptions): Promise<string | undefined> {\n\tif (!options.prettier) return;\n\n\ttry {\n\t\tif (options.verbose) console.log(gray('Loading prettier...'));\n\n\t\tconst { resolveConfig, format } = await import('prettier');\n\t\tconst config = await resolveConfig(destination);\n\t\tif (options.verbose) console.log(gray(`Formatting with prettier config: ${inspect(config, { colors: true })}`));\n\n\t\treturn await format(source, { ...config, filepath: destination });\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tconsole.warn(\n\t\t\tyellow(\n\t\t\t\toptions.verbose\n\t\t\t\t\t? `Failed to format with prettier: ${message}. Continuing with unformatted output.`\n\t\t\t\t\t: 'Failed to format with prettier; install it as a dependency or use --no-prettier. Continuing with unformatted output.'\n\t\t\t)\n\t\t);\n\t}\n\n\treturn undefined;\n}\n\nasync function formatSource(source: string, destination: string, options: GenerateOptions) {\n\treturn (await formatWithOxfmt(source, destination, options)) ?? (await formatWithPrettier(source, destination, options)) ?? source;\n}\n\nexport async function generate([source, destination]: string[], options: GenerateOptions) {\n\tconst sourceDirectory = resolve(source);\n\tconst destinationFile = resolve(destination);\n\tconst i1 = options.indentation;\n\tconst i2 = i1.repeat(2);\n\n\tif (options.verbose) {\n\t\tconst lines = [\n\t\t\t`Source: ${DirectoryIcon} ${green(sourceDirectory)}...`,\n\t\t\t`Output: ${FileIcon} ${green(destinationFile)}...`,\n\t\t\t'',\n\t\t\t'Options:',\n\t\t\t` - Verbose: ${green(options.verbose ? 'yes' : 'no')}`,\n\t\t\t` - Indentation: ${green(JSON.stringify(options.indentation))}`\n\t\t];\n\t\tconsole.log(italic(gray(lines.join('\\n'))));\n\t}\n\n\tconst lines = [\"import 'i18next';\", '', \"declare module 'i18next' {\", `${i1}interface CustomTypeOptions {`, `${i2}resources: {`];\n\n\tawait recurse(lines, sourceDirectory, '', options);\n\t// Intersecting with the mergeable `CustomResources` interface lets consumers add extra keys (e.g. keys\n\t// whose runtime data is provided externally) from their own declaration file without redeclaring\n\t// `resources`, which would otherwise trigger TS2717 (conflicting property declarations).\n\tlines.push(`${i2}} & CustomResources;`, `${i1}}`, '', `${i1}interface CustomResources {}`, '}', '');\n\n\tlet generatedSource = lines.join('\\n');\n\tgeneratedSource = await formatSource(generatedSource, destinationFile, options);\n\tgeneratedSource = annotateGeneratedFile(generatedSource);\n\n\tawait mkdir(dirname(destinationFile), { recursive: true });\n\tawait writeFile(destinationFile, generatedSource, 'utf8');\n}\n\ninterface GenerateOptions {\n\tverbose: boolean;\n\toxfmt: boolean;\n\tprettier: boolean;\n\tindentation: string;\n}\n","#!/usr/bin/env node\n\nimport { defineCommand, runCommand, showUsage } from 'citty';\nimport { readFile } from 'node:fs/promises';\nimport { generate } from './generate.js';\n\nconst packageFile = new URL('../package.json', import.meta.url);\nconst packageJson = JSON.parse(await readFile(packageFile, 'utf-8'));\n\nconst parseIndentation = (value: string): string => {\n\tif (value === 'tabs') return '\\t';\n\n\tconst parsed = Number(value);\n\tif (Number.isNaN(parsed)) throw new Error('The indentation must be a number or \"tabs\"');\n\treturn ' '.repeat(parsed);\n};\n\nconst main = defineCommand({\n\tmeta: {\n\t\tname: 'i18next-type-generator',\n\t\tversion: packageJson.version,\n\t\tdescription: packageJson.description\n\t},\n\targs: {\n\t\tsource: {\n\t\t\ttype: 'positional',\n\t\t\tdescription: 'The directory to generate types from',\n\t\t\tdefault: './src/locales/en-US/'\n\t\t},\n\t\tdestination: {\n\t\t\ttype: 'positional',\n\t\t\tdescription: 'The directory to generate types to',\n\t\t\tdefault: './src/@types/i18next.d.ts'\n\t\t},\n\t\tindentation: {\n\t\t\ttype: 'string',\n\t\t\tdescription: 'The indentation to use',\n\t\t\talias: 'i',\n\t\t\tdefault: 'tabs'\n\t\t},\n\t\tverbose: {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Verbose output',\n\t\t\talias: 'v'\n\t\t},\n\t\tprettier: {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Format output with prettier',\n\t\t\tdefault: true\n\t\t},\n\t\toxfmt: {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Format output with oxfmt',\n\t\t\tdefault: true\n\t\t}\n\t},\n\tasync run({ args }) {\n\t\tawait generate([args.source, args.destination], {\n\t\t\tverbose: args.verbose,\n\t\t\toxfmt: args.oxfmt,\n\t\t\tprettier: args.prettier,\n\t\t\tindentation: parseIndentation(args.indentation)\n\t\t});\n\t}\n});\n\nconst rawArgs = process.argv.slice(2);\n\nif (rawArgs.includes('--help') || rawArgs.includes('-h')) {\n\tawait showUsage(main);\n\tprocess.exit(0);\n}\n\nif (rawArgs.includes('--version')) {\n\tconsole.log(packageJson.version);\n\tprocess.exit(0);\n}\n\ntry {\n\tawait runCommand(main, { rawArgs });\n} catch (error) {\n\tconsole.error(error instanceof Error ? error.message : error);\n\tprocess.exit(1);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","names":[],"sources":["../src/generate.ts","../src/cli.ts"],"sourcesContent":["import { gray, green, italic, yellow } from 'colorette';\nimport { mkdir, opendir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname, join, resolve } from 'node:path';\nimport { inspect } from 'node:util';\n\nconst ci = 'CI' in process.env && process.env.CI !== 'false';\n\nconst FileIcon = ci ? '📄' : '\\uE628';\nconst DirectoryIcon = ci ? '📂' : '\\uF413';\n\nconst GENERATED_FILE_HEADER = ['// This file is automatically generated, do not edit it.', '/* eslint-disable */', '/* oxlint-disable */'] as const;\n\nconst FORMATTER_IGNORE = ['// oxfmt-ignore', '// prettier-ignore'] as const;\n\n/**\n * Inject formatter and linter ignore directives into the already-formatted output.\n *\n * The file-level `eslint-disable` / `oxlint-disable` comments suppress all lint rules, while the\n * per-statement `oxfmt-ignore` / `prettier-ignore` comments protect the two top-level statements\n * (the `i18next` import and the `declare module` block), since neither formatter supports a\n * whole-file inline ignore.\n * @param source The formatted generated source.\n */\nexport function annotateGeneratedFile(source: string): string {\n\tconst ignore = FORMATTER_IGNORE.join('\\n');\n\tconst annotated = source\n\t\t.replace(/^(import\\s+['\"]i18next['\"])/m, `${ignore}\\n$1`)\n\t\t.replace(/^(declare\\s+module\\s+['\"]i18next['\"])/m, `${ignore}\\n$1`);\n\n\treturn `${GENERATED_FILE_HEADER.join('\\n')}\\n${annotated}`;\n}\n\n/**\n * Recursively walk through the directory and generate the types.\n * @param path The path to walk through.\n * @param namespace The namespace to use.\n */\nasync function recurse(lines: string[], path: string, namespace: string, options: GenerateOptions) {\n\tconst indent = options.indentation.repeat(3);\n\n\tif (options.verbose) console.log(gray(`Reading directory ${DirectoryIcon} ${green(path)}...`));\n\n\tconst entries = [];\n\tfor await (const dirent of await opendir(path)) {\n\t\tentries.push(dirent);\n\t}\n\tentries.sort((a, b) => a.name.localeCompare(b.name));\n\n\tfor (const dirent of entries) {\n\t\tconst file = join(path, dirent.name);\n\t\tif (dirent.isFile()) {\n\t\t\tif (!dirent.name.endsWith('.json')) continue;\n\t\t\tif (options.verbose) console.log(gray(`Processing ${FileIcon} ${green(file)}...`));\n\n\t\t\tconst name = dirent.name.slice(0, -5);\n\t\t\tconst key = JSON.stringify(namespace ? `${namespace}/${name}` : name);\n\t\t\tconst data = JSON.stringify(JSON.parse(await readFile(file, 'utf8')), undefined, options.indentation);\n\t\t\tlines.push(`${indent}${key}: ${data.replaceAll('\\n', `\\n${indent}`)};`);\n\t\t} else if (dirent.isDirectory()) {\n\t\t\tawait recurse(lines, file, namespace ? `${namespace}/${dirent.name}` : dirent.name, options);\n\t\t}\n\t}\n}\n\nasync function formatWithOxfmt(source: string, destination: string, options: GenerateOptions): Promise<string | undefined> {\n\tif (!options.oxfmt) return;\n\n\ttry {\n\t\tif (options.verbose) console.log(gray('Loading oxfmt...'));\n\n\t\tconst { format } = await import('oxfmt');\n\t\tconst { code, errors } = await format(destination, source);\n\t\tif (errors.length > 0) {\n\t\t\tthrow new Error(errors.map((error) => error.message).join('\\n'));\n\t\t}\n\n\t\tif (options.verbose) console.log(gray('Formatting with oxfmt.'));\n\n\t\treturn code;\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tconsole.warn(\n\t\t\tyellow(\n\t\t\t\toptions.verbose\n\t\t\t\t\t? `Failed to format with oxfmt: ${message}. Continuing with unformatted output.`\n\t\t\t\t\t: 'Failed to format with oxfmt; install it as a dependency or use --no-oxfmt. Continuing with unformatted output.'\n\t\t\t)\n\t\t);\n\t}\n\n\treturn undefined;\n}\n\nasync function formatWithPrettier(source: string, destination: string, options: GenerateOptions): Promise<string | undefined> {\n\tif (!options.prettier) return;\n\n\ttry {\n\t\tif (options.verbose) console.log(gray('Loading prettier...'));\n\n\t\tconst { resolveConfig, format } = await import('prettier');\n\t\tconst config = await resolveConfig(destination);\n\t\tif (options.verbose) console.log(gray(`Formatting with prettier config: ${inspect(config, { colors: true })}`));\n\n\t\treturn await format(source, { ...config, filepath: destination });\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tconsole.warn(\n\t\t\tyellow(\n\t\t\t\toptions.verbose\n\t\t\t\t\t? `Failed to format with prettier: ${message}. Continuing with unformatted output.`\n\t\t\t\t\t: 'Failed to format with prettier; install it as a dependency or use --no-prettier. Continuing with unformatted output.'\n\t\t\t)\n\t\t);\n\t}\n\n\treturn undefined;\n}\n\nasync function formatSource(source: string, destination: string, options: GenerateOptions) {\n\treturn (await formatWithOxfmt(source, destination, options)) ?? (await formatWithPrettier(source, destination, options)) ?? source;\n}\n\nexport async function generate([source, destination]: string[], options: GenerateOptions) {\n\tconst sourceDirectory = resolve(source);\n\tconst destinationFile = resolve(destination);\n\tconst i1 = options.indentation;\n\tconst i2 = i1.repeat(2);\n\n\tif (options.verbose) {\n\t\tconst lines = [\n\t\t\t`Source: ${DirectoryIcon} ${green(sourceDirectory)}...`,\n\t\t\t`Output: ${FileIcon} ${green(destinationFile)}...`,\n\t\t\t'',\n\t\t\t'Options:',\n\t\t\t` - Verbose: ${green(options.verbose ? 'yes' : 'no')}`,\n\t\t\t` - Indentation: ${green(JSON.stringify(options.indentation))}`\n\t\t];\n\t\tconsole.log(italic(gray(lines.join('\\n'))));\n\t}\n\n\tconst lines = [\"import 'i18next';\", '', \"declare module 'i18next' {\", `${i1}interface CustomTypeOptions {`, `${i2}resources: {`];\n\n\tawait recurse(lines, sourceDirectory, '', options);\n\t// Intersecting with the mergeable `CustomResources` interface lets consumers add extra keys (e.g. keys\n\t// whose runtime data is provided externally) from their own declaration file without redeclaring\n\t// `resources`, which would otherwise trigger TS2717 (conflicting property declarations).\n\tlines.push(`${i2}} & CustomResources;`, `${i1}}`, '', `${i1}interface CustomResources {}`, '}', '');\n\n\tlet generatedSource = lines.join('\\n');\n\tgeneratedSource = await formatSource(generatedSource, destinationFile, options);\n\tgeneratedSource = annotateGeneratedFile(generatedSource);\n\n\tawait mkdir(dirname(destinationFile), { recursive: true });\n\tawait writeFile(destinationFile, generatedSource, 'utf8');\n}\n\ninterface GenerateOptions {\n\tverbose: boolean;\n\toxfmt: boolean;\n\tprettier: boolean;\n\tindentation: string;\n}\n","#!/usr/bin/env node\n\nimport { defineCommand, runCommand, showUsage } from 'citty';\nimport { readFile } from 'node:fs/promises';\nimport { generate } from './generate.js';\n\nconst packageFile = new URL('../package.json', import.meta.url);\nconst packageJson = JSON.parse(await readFile(packageFile, 'utf-8'));\n\nconst parseIndentation = (value: string): string => {\n\tif (value === 'tabs') return '\\t';\n\n\tconst parsed = Number(value);\n\tif (Number.isNaN(parsed)) throw new Error('The indentation must be a number or \"tabs\"');\n\treturn ' '.repeat(parsed);\n};\n\nconst main = defineCommand({\n\tmeta: {\n\t\tname: 'i18next-type-generator',\n\t\tversion: packageJson.version,\n\t\tdescription: packageJson.description\n\t},\n\targs: {\n\t\tsource: {\n\t\t\ttype: 'positional',\n\t\t\tdescription: 'The directory to generate types from',\n\t\t\tdefault: './src/locales/en-US/'\n\t\t},\n\t\tdestination: {\n\t\t\ttype: 'positional',\n\t\t\tdescription: 'The directory to generate types to',\n\t\t\tdefault: './src/@types/i18next.d.ts'\n\t\t},\n\t\tindentation: {\n\t\t\ttype: 'string',\n\t\t\tdescription: 'The indentation to use',\n\t\t\talias: 'i',\n\t\t\tdefault: 'tabs'\n\t\t},\n\t\tverbose: {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Verbose output',\n\t\t\talias: 'v'\n\t\t},\n\t\tprettier: {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Format output with prettier',\n\t\t\tdefault: true\n\t\t},\n\t\toxfmt: {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Format output with oxfmt',\n\t\t\tdefault: true\n\t\t}\n\t},\n\tasync run({ args }) {\n\t\tawait generate([args.source, args.destination], {\n\t\t\tverbose: args.verbose ?? false,\n\t\t\toxfmt: args.oxfmt,\n\t\t\tprettier: args.prettier,\n\t\t\tindentation: parseIndentation(args.indentation)\n\t\t});\n\t}\n});\n\nconst rawArgs = process.argv.slice(2);\n\nif (rawArgs.includes('--help') || rawArgs.includes('-h')) {\n\tawait showUsage(main);\n\tprocess.exit(0);\n}\n\nif (rawArgs.includes('--version')) {\n\tconsole.log(packageJson.version);\n\tprocess.exit(0);\n}\n\ntry {\n\tawait runCommand(main, { rawArgs });\n} catch (error) {\n\tconsole.error(error instanceof Error ? error.message : error);\n\tprocess.exit(1);\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wolfstar/i18next-type-generator",
3
- "version": "3.1.1",
3
+ "version": "3.1.2-next-20260907104340",
4
4
  "description": "A fast utility that generates the TypeScript augmentation for i18next.",
5
5
  "keywords": [
6
6
  "api",
@@ -42,21 +42,21 @@
42
42
  "provenance": true
43
43
  },
44
44
  "dependencies": {
45
- "citty": "^0.1.6",
45
+ "citty": "^0.2.2",
46
46
  "colorette": "^2.0.20",
47
47
  "tslib": "^2.8.1"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@types/node": "22.15.21",
51
- "@vitest/coverage-v8": "^4.1.8",
51
+ "@vitest/coverage-v8": "^4.1.11",
52
52
  "golar": "^0.1.10",
53
- "tsdown": "^0.22.2",
53
+ "tsdown": "^0.22.14",
54
54
  "typescript": "~7.0.2",
55
- "vitest": "^4.1.8"
55
+ "vitest": "^4.1.11"
56
56
  },
57
57
  "optionalDependencies": {
58
- "oxfmt": "^0.53.0",
59
- "prettier": "^3.5.3"
58
+ "oxfmt": "^0.66.0",
59
+ "prettier": "^3.9.6"
60
60
  },
61
61
  "engines": {
62
62
  "node": ">=20"