Skip to content

cli: emit type definition module on watch start #7

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

Merged
merged 1 commit into from
May 24, 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
41 changes: 24 additions & 17 deletions cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,38 @@
const chokidar = require('chokidar')
const fs = require('fs')
const glob = require('glob')
const { start, buildFluentTypeModule } = require('../dist')
const { start, updateContent, buildFluentTypeModule } = require('../dist')

const startWatcher = (fileSystemApi, typeDefinitionFilepath) => {
const typeDefinitionFilename = `${typeDefinitionFilepath}/translations.ftl.d.ts`

const emitFluentTypeModule = () => {
const fluentTypeModule = buildFluentTypeModule()

fileSystemApi.writeFile(
typeDefinitionFilename,
fluentTypeModule,
{ encoding: 'utf-8' },
(err) => {
if (err) {
console.log('❌ Error')
console.log(err)
return
}

console.log(`🏁 Type definition updated: ${typeDefinitionFilename}`)
}
)
}

glob('**/*.ftl', { ignore: ['node_modules/**/*', '.git/**/*'] }, (errors, matches) => {
const files = matches.map(path => ({
path,
content: fileSystemApi.readFileSync(path, { encoding: 'utf-8' }),
}))

start(files)
emitFluentTypeModule()
})

const watcher = chokidar.watch('**/*.ftl', { ignored: ['node_modules/**/*', '.git/**/*'] })
Expand All @@ -25,22 +45,9 @@ const startWatcher = (fileSystemApi, typeDefinitionFilepath) => {
console.log(`🔍 File was changed: ${path}`)

const content = fileSystemApi.readFileSync(path, { encoding: 'utf-8' })
const fluentTypeModule = buildFluentTypeModule({ path, content })

fileSystemApi.writeFile(
typeDefinitionFilename,
fluentTypeModule,
{ encoding: 'utf-8' },
(err) => {
if (err) {
console.log('❌ Error')
console.log(err)
return
}

console.log(`🏁 Type definition updated: ${typeDefinitionFilename}`)
}
)
updateContent({ path, content })

emitFluentTypeModule()
})
}

Expand Down
9 changes: 4 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ import { updateGlobalState } from './global-state'
const start = (files: CliFluentFile[]) =>
files.forEach(file => updateGlobalState({ type: 'addContent', payload: file }))

const buildFluentTypeModule = (file: CliFluentFile) => {
const updateContent = (file: CliFluentFile) =>
updateGlobalState({ type: 'updateContent', payload: file })
const fluentTypeModule = build()
return fluentTypeModule
}

const buildFluentTypeModule = build

// TODO: is necessary to export as common js to be available to cli.js
// but probably there are better approach to do that
module.exports = { start, buildFluentTypeModule }
module.exports = { start, updateContent, buildFluentTypeModule }
48 changes: 42 additions & 6 deletions test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import dedent from 'dedent-js'
const { buildFluentTypeModule, start } = require('../src')
const { start, updateContent, buildFluentTypeModule } = require('../src')

test('Should match the types definitions', async () => {
const fixturePt = dedent`
const fixturePtFirstVersion = dedent`
hello = Olá { $firstName }
how-are-you = Como você está?
bye = Tchau
Expand All @@ -13,13 +13,12 @@ test('Should match the types definitions', async () => {
`

start([
{ path: 'pt.ftl', content: fixturePt },
{ path: 'pt.ftl', content: fixturePtFirstVersion },
{ path: 'jp.ftl', content: fixtureJp },
])

const fluentTypeModule = buildFluentTypeModule({ path: 'pt.ftl', content: fixturePt })

expect(fluentTypeModule).toBe(dedent`
const fluentTypeModuleFirstVersion = buildFluentTypeModule()
expect(fluentTypeModuleFirstVersion).toBe(dedent`
// This file is automatically generated.
// Please do not change this file!

Expand Down Expand Up @@ -51,4 +50,41 @@ test('Should match the types definitions', async () => {
: never
)
`)

const fixturePtSecondVersion = dedent`
hello = Olá { $firstName }
how-are-you = Como você está?
`
updateContent({ path: 'pt.ftl', content: fixturePtSecondVersion })

const fluentTypeModuleSecondVersion = buildFluentTypeModule()
expect(fluentTypeModuleSecondVersion).toBe(dedent`
// This file is automatically generated.
// Please do not change this file!

import { FluentBundle, FluentArgument } from '@fluent/bundle'

type Message<T extends MessagesKey> = {
id: T
value: T
attributes: Record<string, T>
}

declare global {
interface FluentBundleTyped extends FluentBundle {
getMessage<T extends MessagesKey>(id: T): Message<T>
formatPattern: <T extends MessagesKey>(...args: PatternArguments<T>) => string
}
}

type MessagesKey = 'hello' |
'how-are-you'
type PatternArguments<T extends MessagesKey> = (
T extends 'hello'
? [T, { 'firstName': FluentArgument,'lastName': FluentArgument }]:
T extends 'how-are-you'
? [T]
: never
)
`)
})