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: bundle and namespace features #78

Merged
merged 3 commits into from
Jan 27, 2020
Merged
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
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,19 @@
"@vue/component-compiler-utils": "^3.0.0",
"debug": "^4.1.1",
"deep-diff": "^1.0.2",
"deepmerge": "^4.2.2",
"flat": "^5.0.0",
"glob": "^7.1.4",
"js-yaml": "^3.13.1",
"json-diff": "^0.5.4",
"json5": "^2.1.0",
"vue-template-compiler": "^2.6.10",
"yargs": "^15.0.0"
"yargs": "^15.1.0"
},
"devDependencies": {
"@types/debug": "^4.1.4",
"@types/deep-diff": "^1.0.0",
"@types/deepmerge": "^2.2.0",
"@types/flat": "^0.0.28",
"@types/glob": "^7.1.1",
"@types/jest": "^24.0.24",
Expand Down
28 changes: 6 additions & 22 deletions src/commands/diff.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Arguments, Argv } from 'yargs'
const { diffString } = require('json-diff') // NOTE: not provided type definition ...
import { DiffError, fail } from './fails/diff'

import {
resolveProviderConf,
Expand All @@ -22,8 +23,6 @@ export const command = 'diff'
export const aliases = 'df'
export const describe = 'Diff locale messages between local and localization service'

class DiffError extends Error {}

export const builder = (args: Argv): Argv<DiffOptions> => {
return args
.option('provider', {
Expand Down Expand Up @@ -62,37 +61,22 @@ export const builder = (args: Argv): Argv<DiffOptions> => {
alias: 'n',
describe: 'option for the locale messages structure, you can specify the option, if you hope to normalize for the provider.'
})
.fail((msg, err) => {
if (msg) {
// TODO: should refactor console message
console.error(msg)
process.exit(1)
} else {
if (err instanceof DiffError) {
// TODO: should refactor console message
console.warn(err.message)
process.exit(64)
} else {
// TODO: should refactor console message
console.error(err.message)
process.exit(1)
}
}
})
.fail(fail)
}

export const handler = async (args: Arguments<DiffOptions>): Promise<unknown> => {
const { normalize } = args
const format = 'json'

const ProviderFactory = loadProvider(args.provider)

if (ProviderFactory === null) {
throw new Error(`Not found ${args.provider} provider`)
return Promise.reject(new Error(`Not found ${args.provider} provider`))
}

if (!args.target && !args.targetPaths) {
// TODO: should refactor console message
throw new Error('You need to specify either --target or --target-paths')
return Promise.reject(new Error('You need to specify either --target or --target-paths'))
}

const confPath = resolveProviderConf(args.provider, args.conf)
Expand All @@ -108,7 +92,7 @@ export const handler = async (args: Arguments<DiffOptions>): Promise<unknown> =>
console.log(ret)

if (ret) {
throw new DiffError('There are differences!')
return Promise.reject(new DiffError('There are differences!'))
}

return Promise.resolve()
Expand Down
10 changes: 10 additions & 0 deletions src/commands/fails/diff.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ExitCode } from './exitcode'
import defineFail from './fail'

export class DiffError extends Error {}
export const fail = defineFail(DiffError, ExitCode.Difference)

export default {
DiffError,
fail
}
6 changes: 6 additions & 0 deletions src/commands/fails/exitcode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const enum ExitCode {
NotYetTranslation = 4,
UndefinedLocaleMessage = 5,
Difference = 64
}

29 changes: 29 additions & 0 deletions src/commands/fails/fail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { ExitCode } from './exitcode'

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Constructor<T> = { new (...args: any[]): T }

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function typeGuard<T> (o: any, className: Constructor<T>): o is T {
return o instanceof className
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export default function defineFail (UserError: any, code: ExitCode) {
return (msg: string, err: Error) => {
if (msg) {
// TODO: should refactor console message
console.error(msg)
process.exit(1)
} else {
if (typeGuard(err, UserError)) {
// TODO: should refactor console message
console.warn(err.message)
process.exit(code)
} else {
// preserve statck! see the https://github.com/yargs/yargs/blob/master/docs/api.md#failfn
throw err
}
}
}
}
10 changes: 10 additions & 0 deletions src/commands/fails/list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ExitCode } from './exitcode'
import defineFail from './fail'

export class LocaleMessageUndefindError extends Error {}
export const fail = defineFail(LocaleMessageUndefindError, ExitCode.UndefinedLocaleMessage)

export default {
LocaleMessageUndefindError,
fail
}
10 changes: 10 additions & 0 deletions src/commands/fails/status.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ExitCode } from './exitcode'
import defineFail from './fail'

export class TranslationStatusError extends Error {}
export const fail = defineFail(TranslationStatusError, ExitCode.NotYetTranslation)

export default {
TranslationStatusError,
fail
}
72 changes: 67 additions & 5 deletions src/commands/infuse.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
import { Arguments, Argv } from 'yargs'

import { resolve, parsePath, readSFC } from '../utils'
import {
resolve,
parsePath,
readSFC,
NamespaceDictionary,
loadNamespaceDictionary,
splitLocaleMessages
} from '../utils'

import infuse from '../infuser'
import squeeze from '../squeezer'
import fs from 'fs'
import path from 'path'
import { applyDiff } from 'deep-diff'
import glob from 'glob'
import { LocaleMessages, SFCFileInfo, MetaLocaleMessage, Locale } from '../../types'
import {
Locale,
LocaleMessages,
SFCFileInfo,
MetaLocaleMessage,
MetaExternalLocaleMessages
} from '../../types'

import { debug as Debug } from 'debug'
const debug = Debug('vue-i18n-locale-message:commands:infuse')
Expand All @@ -16,6 +30,9 @@ type InfuseOptions = {
target: string
locales: string
match?: string
unbundleTo?: string
unbundleMatch?: string
namespace?: string
dryRun: boolean
}

Expand All @@ -42,6 +59,21 @@ export const builder = (args: Argv): Argv<InfuseOptions> => {
alias: 'm',
describe: 'option should be accepted a regex filenames, must be specified together --messages'
})
.option('unbundleTo', {
type: 'string',
alias: 'u',
describe: `target path of external locale messages bundled with 'squeeze' command, can also be specified multi paths with comma delimiter`
})
.option('unbundleMatch', {
type: 'string',
alias: 'M',
describe: `option should be accepted regex filename of external locale messages, must be specified if it's directory path of external locale messages with --unbundle-to`
})
.option('namespace', {
type: 'string',
alias: 'n',
describe: 'file path that defines the namespace for external locale messages bundled together'
})
.option('dryRun', {
type: 'boolean',
alias: 'd',
Expand All @@ -50,15 +82,38 @@ export const builder = (args: Argv): Argv<InfuseOptions> => {
})
}

export const handler = (args: Arguments<InfuseOptions>): void => {
export const handler = async (args: Arguments<InfuseOptions>) => {
const targetPath = resolve(args.target)
const messagesPath = resolve(args.locales)

let nsDictionary = {} as NamespaceDictionary
try {
if (args.namespace) {
nsDictionary = await loadNamespaceDictionary(args.namespace)
}
} catch (e) {
console.warn('cannot load namespace dictionary')
}
debug('namespace dictionary:', nsDictionary)

const sources = readSFC(targetPath)
const messages = readLocaleMessages(messagesPath, args.match)

const { sfc, external } = splitLocaleMessages(messages, nsDictionary, args.unbundleTo, args.unbundleMatch)
debug('sfc', sfc)
debug('external', external)

const meta = squeeze(targetPath, sources)
apply(messages, meta)
apply(sfc, meta)
const newSources = infuse(targetPath, sources, meta)
if (!args.dryRun) writeSFC(newSources)

if (!args.dryRun) {
writeSFC(newSources)
}

if (!args.dryRun && external) {
writeExternalLocaleMessages(external)
}
}

function readLocaleMessages (targetPath: string, matchRegex?: string): LocaleMessages {
Expand Down Expand Up @@ -186,6 +241,13 @@ function writeSFC (sources: SFCFileInfo[]) {
})
}

function writeExternalLocaleMessages (meta: MetaExternalLocaleMessages[]) {
// TODO: async implementation
meta.forEach(({ path, messages }) => {
fs.writeFileSync(path, JSON.stringify(messages, null, 2))
})
}

export default {
command,
aliases,
Expand Down
25 changes: 5 additions & 20 deletions src/commands/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import fs from 'fs'
import { promisify } from 'util'
import { Arguments, Argv } from 'yargs'

import { LocaleMessageUndefindError, fail } from './fails/list'

import {
resolve,
getLocaleMessages
Expand Down Expand Up @@ -36,8 +38,6 @@ const debug = Debug('vue-i18n-locale-message:commands:list')

const writeFile = promisify(fs.writeFile)

class LocaleMessageUndefindError extends Error {}

export const command = 'list'
export const aliases = 'lt'
export const describe = 'List undefined fields in locale messages'
Expand Down Expand Up @@ -77,29 +77,14 @@ export const builder = (args: Argv): Argv<ListOptions> => {
default: 2,
describe: `option for indent of locale message, if you need to adjust with --define option`
})
.fail((msg, err) => {
if (msg) {
// TODO: should refactor console message
console.error(msg)
process.exit(1)
} else {
if (err instanceof LocaleMessageUndefindError) {
// TODO: should refactor console message
console.warn(err.message)
process.exit(5)
} else {
if (err) throw err
}
}
})
.fail(fail)
}

export const handler = async (args: Arguments<ListOptions>): Promise<unknown> => {
const { locale, define } = args
if (!args.target && !args.targetPaths) {
// TODO: should refactor console message
console.error('You need to specify either --target or --target-paths')
return
return Promise.reject(new Error('You need to specify either --target or --target-paths'))
}

const localeMessages = getLocaleMessages(args)
Expand Down Expand Up @@ -134,7 +119,7 @@ export const handler = async (args: Arguments<ListOptions>): Promise<unknown> =>
})

if (!define && !valid) {
return Promise.reject(new LocaleMessageUndefindError('there are undefined fields in the target locale messages, you can define with --define option'))
return Promise.reject(new LocaleMessageUndefindError('There are undefined fields in the target locale messages, you can define with --define option'))
}

const unflattedLocaleMessages = {} as LocaleMessages
Expand Down
Loading