@drone1/alt
Version:
An AI-powered localization tool
142 lines (125 loc) • 3.54 kB
JavaScript
import * as os from 'os'
import * as fs from 'fs'
import * as fsp from 'fs/promises'
import * as path from 'path'
import stripJsonComments from 'strip-json-comments'
import { ensureExtension, normalizeKey } from './utils.js'
import { assertIsObj, assertValidPath } from './assert.js'
import { pathToFileURL } from 'url'
import { CWD } from './consts.js'
import { localizeFormatted } from '../localizer/localize.js'
export async function mkTmpDir() {
return await fsp.mkdtemp(path.join(os.tmpdir(), 'alt-'))
}
export function parseJson(s) {
try {
return JSON.parse(s)
} catch (e) {
return null
}
}
export async function readFileAsText(filePath) {
try {
return await fsp.readFile(filePath, 'utf8')
} catch (error) {
if (error.code === 'ENOENT') {
return null
}
throw error
}
}
export async function readJsonFile(filePath, isJSONComments = false) {
let content = await readFileAsText(filePath)
if (isJSONComments) content = stripJsonComments(content)
return parseJson(content)
}
export async function fileExists(path) {
try {
await fsp.access(path)
return true
} catch {
return false
}
}
export function rmDir(dir, log) {
try {
fs.rmSync(dir, { recursive: true, force: true })
log.D(`Removed dir ${dir}`)
} catch (error) {
log.E(`Error cleaning up temp directory "${dir}": ${error.message}`)
throw error
}
}
// This is basically so that we can dynamically import .js files by copying them to temp .mjs files, to avoid errors from node
export async function copyFileToTempAndEnsureExtension({ appLang, filePath, tmpDir, ext, log }) {
try {
const fileName = ensureExtension(path.basename(filePath), ext)
const destPath = path.join(tmpDir, fileName)
await fsp.copyFile(filePath, destPath)
return destPath
} catch (error) {
throw new Error(
localizeFormatted({
token: 'error-copying-file-to-temp-dir',
data: { error: error.message },
lang: appLang,
log
})
)
}
}
// Dynamically imports the javascript file at filePath, which can be relative or absolute
export async function importJsFile(filePath) {
if (!path.isAbsolute(filePath)) {
filePath = path.resolve(CWD, filePath)
}
// Convert the file path to a proper URL
const fileUrl = pathToFileURL(filePath)
return await import(fileUrl)
}
export function normalizeOutputPath({ dir, filename, normalize }) {
return path.join(dir, normalize ? filename.toLowerCase() : filename)
}
export function writeJsonFile(filePath, data, log) {
assertValidPath(filePath)
assertIsObj(data)
log.V(`Preparing to write ${filePath}...`)
// Create normalized version of data with consistent key encoding
log.D(`Normalizing data...`)
const normalizedData = {}
for (const [ key, value ] of Object.entries(data)) {
normalizedData[normalizeKey(key)] = value
}
log.D(`Done.`)
try {
const dir = path.dirname(filePath)
log.D(`Ensuring directory ${dir} exists...`)
if (!dirExists(dir, log)) {
log.D(`Directory ${dir} did not exist; creating...`)
fs.mkdirSync(dir, { recursive: true })
}
log.D(`Done.`)
} catch (err) {
log.E(err)
}
log.V(`Writing ${filePath}...`)
try {
fs.writeFileSync(filePath, JSON.stringify(normalizedData, null, 2), 'utf8')
} catch (err) {
log.E(err)
}
log.D(`Done.`)
}
export function dirExists(dir, log) {
try {
log.D(`fetching stats for ${dir}...`)
return fs.statSync(dir).isDirectory()
} catch (error) {
log.E(error)
return false
}
}
export function ensureDir(dir, log) {
if (dirExists(dir, log)) return
fs.mkdirSync(dir, { recursive: true })
}