Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add possibility to override default path to config file #667

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions packages/cli/src/cli.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Command } from 'commander'
import { Command, Option } from 'commander'
import { checkAndUpdateSchemaVersion } from '../../config/src/update-schema-version.mjs'
import { startGenerator } from '../../generator/src/generator.mjs'
import { logger } from '../../generator/src/utils/logger.mjs'
Expand All @@ -13,6 +13,9 @@ program.description('CLI to read the base translation file and generate types')
program.option('--no-watch', 'run the generator only once (CI)')
program.option('--setup', 'step-by-step setup')
program.option('--setup-auto', 'auto-guess setup')
program.addOption(
new Option('-p, --project <path>', 'path to the config file').default('.typesafe-i18n.json').makeOptionMandatory(),
)

program.version(version)

Expand All @@ -22,12 +25,12 @@ const run = async () => {

logger.info(`version ${version}`)

await checkAndUpdateSchemaVersion()
await checkAndUpdateSchemaVersion(options.project)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add a validation here?
The string should end with .json and we should check if the file exists (except if it is a setup call).


if (options.setup || options.setupAuto) {
await setup(options.setupAuto)
} else {
startGenerator(undefined, options['watch'])
startGenerator(options.project, options['watch'])
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/setup/setup.mts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export const setup = async (autoSetup: boolean) => {

const config = await getConfigDiff(options)

await writeConfigToFile(config)
await writeConfigToFile(config, '.typesafe-i18n.json')
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't you need to use options.project here too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I wrote this, I think that this setup method is used only for in-place config generation, not for generate config in path passed by --project path

We can add path here too if needed

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be more consistent if someone is able to pass the -p flag also to the setup function.

logger.info(`generated config file: '.typesafe-i18n.json'`)

const installed = await installDependencies()
Expand Down
15 changes: 9 additions & 6 deletions packages/config/src/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ import { applyDefaultValues } from './core.mjs'
import type { GeneratorConfig, GeneratorConfigWithDefaultValues } from './types.mjs'
import { validateConfig } from './validation.mjs'

export const writeConfigToFile = async (config: GeneratorConfig) =>
writeConfigFile({ ...config, $schema: `https://unpkg.com/typesafe-i18n@${version}/schema/typesafe-i18n.json` })
export const writeConfigToFile = async (config: GeneratorConfig, configPath: string) =>
writeConfigFile(
{ ...config, $schema: `https://unpkg.com/typesafe-i18n@${version}/schema/typesafe-i18n.json` },
configPath,
)

export const doesConfigFileExist = async () => doesPathExist(resolve('.typesafe-i18n.json'))

export const readRawConfig = async () =>
(await importFile<GeneratorConfig & { $schema?: string }>(resolve('.typesafe-i18n.json'), false)) || {}
export const readRawConfig = async (configPath: string) =>
(await importFile<GeneratorConfig & { $schema?: string }>(resolve(configPath), false)) || {}

export const readConfig = async (): Promise<GeneratorConfig> => {
const generatorConfig = await readRawConfig()
export const readConfig = async (configPath = '.typesafe-i18n.json'): Promise<GeneratorConfig> => {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not use default values anywhere. This makes it easy to miss a spot where we forgot to pass it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you have some ideas, how we can save backward compatibility with previous codebase that have hardcoded path to file, without default values?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally it get's passed from the CLI and .typesafe-i18n.json is the default value there if -p does not get specified.
Without having a look at the code, I currently don't really know where this function get's called. But the call stack to this function should only be initiated from the CLI or the exporter & importer I think

const generatorConfig = await readRawConfig(configPath)

// remove "$schema" property
const configWithoutSchemaAttribute = Object.fromEntries(
Expand Down
12 changes: 6 additions & 6 deletions packages/config/src/core.mts
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,22 @@ export const applyDefaultValues = async (
...(config as unknown as any),
})

const readConfigFromDisk = async (fs: FileSystemUtil) => {
const content = await fs.readFile('.typesafe-i18n.json').catch(() => '{}')
const readConfigFromDisk = async (fs: FileSystemUtil, configPath: string) => {
const content = await fs.readFile(configPath).catch(() => '{}')

return JSON.parse(content.toString()) as GeneratorConfig & { $schema?: string }
}

export const getConfig = async (fs: FileSystemUtil) => {
const config = await readConfigFromDisk(fs)
export const getConfig = async (fs: FileSystemUtil, configPath = '.typesafe-i18n.json') => {
const config = await readConfigFromDisk(fs, configPath)

return applyDefaultValues(config)
}

// --------------------------------------------------------------------------------------------------------------------

export const getLocaleInformation = async (fs: FileSystemUtil) => {
const config = await getConfig(fs)
export const getLocaleInformation = async (fs: FileSystemUtil, configPath = '.typesafe-i18n.json') => {
const config = await getConfig(fs, configPath)

return {
base: config.baseLocale,
Expand Down
8 changes: 4 additions & 4 deletions packages/config/src/update-schema-version.mts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { logger } from '../../generator/src/utils/logger.mjs'
import { version } from '../../version'
import { readRawConfig, writeConfigToFile } from './config.mjs'

export const checkAndUpdateSchemaVersion = async () => {
const config = await readRawConfig()
export const checkAndUpdateSchemaVersion = async (configPath = '.typesafe-i18n.json') => {
const config = await readRawConfig(configPath)

if (!config.$schema) return

if (config.$schema.includes(version)) return

await writeConfigToFile(config)
await writeConfigToFile(config, configPath)

logger.info(`updated '$schema' version of '.typesafe-i18n.json' to '${version}'`)
logger.info(`updated '$schema' version of '${configPath}' to '${version}'`)
}
5 changes: 2 additions & 3 deletions packages/generator/src/generator.mts
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,11 @@ const debounce = (callback: () => void) =>
++debounceCounter,
)

export const startGenerator = async (config?: GeneratorConfig, watchFiles = true): Promise<void> => {
ivanhofer marked this conversation as resolved.
Show resolved Hide resolved
export const startGenerator = async (configPath: string, watchFiles = true): Promise<void> => {
logger = createLogger(console, !watchFiles)

const parsedConfig = {
...(await readConfig()),
...config,
...(await readConfig(configPath)),
} as GeneratorConfig

const configWithDefaultValues = await getConfigWithDefaultValues(parsedConfig)
Expand Down
4 changes: 2 additions & 2 deletions packages/generator/src/utils/file.utils.mts
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ export const deleteFolderRecursive = async (path: string): Promise<boolean> => {

export const writeFile = (filePath: string, content: string) => write(filePath, content, { encoding: 'utf-8' })

export const writeConfigFile = async (content: JsonObject) =>
writeFile(resolve('./', '.typesafe-i18n.json'), JSON.stringify(content, undefined, 3))
export const writeConfigFile = async (content: JsonObject, configPath: string) =>
writeFile(resolve('./', configPath), JSON.stringify(content, undefined, 3))

const getFileName = (path: string, file: string) => {
const ext = file.endsWith(fileEnding) || file.endsWith(`${fileEnding}x`) || file.endsWith('.d.ts') ? '' : fileEnding
Expand Down