@intlayer/chokidar
Version:
Uses chokidar to scan and build Intlayer declaration files into dictionaries based on Intlayer configuration.
332 lines • 13.5 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var writeJSFile_exports = {};
__export(writeJSFile_exports, {
writeJSFile: () => writeJSFile
});
module.exports = __toCommonJS(writeJSFile_exports);
var import_generator = __toESM(require("@babel/generator"));
var babelParser = __toESM(require("@babel/parser"));
var import_traverse = __toESM(require("@babel/traverse"));
var t = __toESM(require("@babel/types"));
var import_config = require("@intlayer/config");
var import_built = __toESM(require("@intlayer/config/built"));
var import_core = require("@intlayer/core");
var import_fs = require("fs");
var import_promises = require("fs/promises");
var import_path = require("path");
var import_getContentDeclarationFileTemplate = require('../getContentDeclarationFileTemplate/getContentDeclarationFileTemplate.cjs');
var import_formatCode = require('./formatCode.cjs');
const writeJSFile = async (filePath, dictionary) => {
const appLogger = (0, import_config.getAppLogger)(import_built.default);
const {
key: dictionaryIdentifierKey,
content: updatesToApply,
locale,
autoFilled
} = dictionary;
const isPerLocaleDeclarationFile = typeof locale === "string";
if (!(0, import_fs.existsSync)(filePath)) {
const fileExtension = (0, import_path.extname)(filePath);
let format = "ts";
if (fileExtension === ".ts" || fileExtension === ".tsx") {
format = "ts";
} else if (fileExtension === ".cjs" || fileExtension === ".cjsx") {
format = "cjs";
} else {
format = "esm";
}
appLogger("File does not exist, creating it", {
isVerbose: true
});
const template = await (0, import_getContentDeclarationFileTemplate.getContentDeclarationFileTemplate)(
dictionaryIdentifierKey,
format,
{ locale, autoFilled }
);
await (0, import_promises.writeFile)(filePath, template, "utf-8");
}
let sourceCode;
try {
sourceCode = await (0, import_promises.readFile)(filePath, "utf-8");
} catch (error) {
const err = error;
appLogger(`Failed to read file: ${filePath}`, {
level: "error"
});
throw new Error(`Failed to read file ${filePath}: ${err.message}`);
}
const ast = babelParser.parse(sourceCode, {
sourceType: "module",
plugins: ["typescript", "jsx"],
tokens: true
});
let dictionaryObjectPath = null;
let dictionaryIdentifier = null;
(0, import_traverse.default)(ast, {
ObjectExpression(path) {
if (dictionaryObjectPath) return;
const keyProp = path.node.properties.find((prop) => {
if (!t.isObjectProperty(prop)) return false;
if (!t.isIdentifier(prop.key) && !t.isStringLiteral(prop.key))
return false;
const keyName = t.isIdentifier(prop.key) ? prop.key.name : prop.key.value;
if (keyName !== "key" || !t.isStringLiteral(prop.value)) return false;
const propValue = prop.value.value;
return propValue === dictionaryIdentifierKey;
});
if (keyProp) {
dictionaryObjectPath = path;
path.stop();
}
}
});
if (!dictionaryObjectPath) {
appLogger(`Looking for variable declarations`, {
isVerbose: true
});
const candidateVars = [];
(0, import_traverse.default)(ast, {
VariableDeclarator(path) {
const { node } = path;
if (!t.isIdentifier(node.id)) return;
let objPath = null;
if (node.init && t.isObjectExpression(node.init)) {
objPath = path.get("init");
} else if (node.init && (t.isTSAsExpression(node.init) || t.isTSTypeAssertion(node.init)) && t.isObjectExpression(node.init.expression)) {
objPath = path.get("init.expression");
}
if (objPath) {
candidateVars.push({ id: node.id.name, path: objPath });
}
}
});
appLogger(`Found ${candidateVars.length} candidate variables`, {
isVerbose: true
});
for (const { id, path } of candidateVars) {
const keyProp = path.node.properties.find((prop) => {
if (!t.isObjectProperty(prop)) return false;
if (!t.isIdentifier(prop.key) && !t.isStringLiteral(prop.key))
return false;
const keyName = t.isIdentifier(prop.key) ? prop.key.name : prop.key.value;
return keyName === "key" && t.isStringLiteral(prop.value) && prop.value.value === dictionaryIdentifierKey;
});
if (keyProp) {
appLogger(`Found match in variable: ${id}`);
dictionaryObjectPath = path;
dictionaryIdentifier = id;
break;
}
}
if (!dictionaryObjectPath) {
appLogger("Could not find dictionary object. Dumping all objects:", {
isVerbose: true
});
(0, import_traverse.default)(ast, {
ObjectExpression(path) {
const props = path.node.properties.map((prop) => {
if (!t.isObjectProperty(prop)) return "non-object-property";
if (!t.isIdentifier(prop.key) && !t.isStringLiteral(prop.key))
return "complex-key";
const keyName = t.isIdentifier(prop.key) ? prop.key.name : prop.key.value;
let valueDesc = "unknown-value";
if (t.isStringLiteral(prop.value)) {
valueDesc = `"${prop.value.value}"`;
}
return `${keyName}: ${valueDesc}`;
}).join(", ");
appLogger(`Object: { ${props} }`);
}
});
}
}
if (!dictionaryObjectPath) {
throw new Error(
`Could not find dictionary object with key '${dictionaryIdentifierKey}' in ${filePath}`
);
}
const contentPropertyPath = dictionaryObjectPath.get("properties").find((propPath) => {
if (!propPath.isObjectProperty()) return false;
const propNode = propPath.node;
const keyName = t.isIdentifier(propNode.key) ? propNode.key.name : t.isStringLiteral(propNode.key) ? propNode.key.value : null;
return keyName === "content";
});
if (!contentPropertyPath || !contentPropertyPath.isObjectProperty() || !contentPropertyPath.get("value").isObjectExpression()) {
throw new Error(
`Could not find 'content' object property, or it's not an object, in dictionary in ${filePath}`
);
}
const contentObjectPath = contentPropertyPath.get(
"value"
);
const buildValueNodeFromData = (data) => {
if (data?.nodeType === import_core.NodeType.Translation) {
const translationContent = data;
if (isPerLocaleDeclarationFile && typeof locale === "string" && translationContent?.[import_core.NodeType.Translation]?.[locale] !== void 0) {
return buildValueNodeFromData(
translationContent[import_core.NodeType.Translation][locale]
);
}
const translationsObj = t.objectExpression(
Object.entries(translationContent?.[import_core.NodeType.Translation] ?? {}).map(
([langKey, langValue]) => {
const keyNode = t.isValidIdentifier(langKey) ? t.identifier(langKey) : t.stringLiteral(langKey);
return t.objectProperty(keyNode, buildValueNodeFromData(langValue));
}
)
);
return t.callExpression(t.identifier("t"), [translationsObj]);
}
if (Array.isArray(data)) {
return t.arrayExpression(data.map((el) => buildValueNodeFromData(el)));
}
if (data && typeof data === "object") {
const props = Object.entries(data).map(([k, v]) => {
const key = t.isValidIdentifier(k) ? t.identifier(k) : t.stringLiteral(k);
return t.objectProperty(key, buildValueNodeFromData(v));
});
return t.objectExpression(props);
}
switch (typeof data) {
case "string":
return t.stringLiteral(data);
case "number":
return t.numericLiteral(data);
case "boolean":
return t.booleanLiteral(data);
default:
return t.nullLiteral();
}
};
const ensureObjectProperty = (objPath, key) => {
const existing = objPath.get("properties").find((propPath) => {
if (!propPath.isObjectProperty()) return false;
const propNode = propPath.node;
const keyName = t.isIdentifier(propNode.key) ? propNode.key.name : t.isStringLiteral(propNode.key) ? propNode.key.value : null;
return keyName === key;
});
if (existing) return existing;
const keyNode = t.isValidIdentifier(key) ? t.identifier(key) : t.stringLiteral(key);
const newProp = t.objectProperty(keyNode, t.objectExpression([]));
objPath.node.properties.push(newProp);
const props = objPath.get("properties");
return props[props.length - 1];
};
const mergeValueIntoProperty = (propPath, value, propKeyForLogs) => {
const valuePath = propPath.get("value");
if (value?.nodeType === import_core.NodeType.Translation) {
const translationContent = value;
if (valuePath.isCallExpression() && t.isIdentifier(valuePath.node.callee) && valuePath.node.callee.name === "t") {
const translationsObj = t.objectExpression(
Object.entries(translationContent?.[import_core.NodeType.Translation] ?? {}).map(
([langKey, langValue]) => t.objectProperty(
t.isValidIdentifier(langKey) ? t.identifier(langKey) : t.stringLiteral(langKey),
buildValueNodeFromData(langValue)
)
)
);
if (isPerLocaleDeclarationFile && typeof locale === "string") {
const localized = translationContent?.[import_core.NodeType.Translation]?.[locale];
if (localized !== void 0) {
valuePath.replaceWith(buildValueNodeFromData(localized));
return;
}
}
valuePath.node.arguments = [translationsObj];
return;
}
valuePath.replaceWith(buildValueNodeFromData(value));
return;
}
if (Array.isArray(value)) {
valuePath.replaceWith(buildValueNodeFromData(value));
return;
}
if (value && typeof value === "object") {
if (!valuePath.isObjectExpression()) {
valuePath.replaceWith(t.objectExpression([]));
}
const objPath = valuePath;
for (const [k, v] of Object.entries(value)) {
const childProp = ensureObjectProperty(objPath, k);
mergeValueIntoProperty(childProp, v, `${propKeyForLogs}.${k}`);
}
return;
}
valuePath.replaceWith(buildValueNodeFromData(value));
return;
};
for (const [entryKeyToUpdate, newEntryData] of Object.entries(
updatesToApply
)) {
let targetPropertyPath = contentObjectPath.get("properties").find((propPath) => {
if (!propPath.isObjectProperty()) return false;
const propNode = propPath.node;
const keyName = t.isIdentifier(propNode.key) ? propNode.key.name : t.isStringLiteral(propNode.key) ? propNode.key.value : null;
return keyName === entryKeyToUpdate;
});
if (!targetPropertyPath) {
const keyNode = t.isValidIdentifier(entryKeyToUpdate) ? t.identifier(entryKeyToUpdate) : t.stringLiteral(entryKeyToUpdate);
const newProperty = t.objectProperty(keyNode, t.objectExpression([]));
contentObjectPath.node.properties.push(newProperty);
const props = contentObjectPath.get("properties");
targetPropertyPath = props[props.length - 1];
}
mergeValueIntoProperty(targetPropertyPath, newEntryData, entryKeyToUpdate);
}
const generatedCode = (0, import_generator.default)(ast, {
retainLines: true,
comments: true,
jsescOption: {
minimal: true
// This ensures Unicode characters are not escaped
}
}).code;
let finalCode = generatedCode;
finalCode = await (0, import_formatCode.formatCode)(filePath, finalCode);
try {
await (0, import_promises.writeFile)(filePath, finalCode, "utf-8");
(0, import_config.logger)(`Successfully updated ${filePath}`, {
level: "info",
isVerbose: true
});
} catch (error) {
const err = error;
(0, import_config.logger)(`Failed to write updated file: ${filePath}`, {
level: "error"
});
throw new Error(`Failed to write updated file ${filePath}: ${err.message}`);
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
writeJSFile
});
//# sourceMappingURL=writeJSFile.cjs.map