@salesforce/core
Version:
Core libraries to interact with SFDX projects, orgs, and APIs.
85 lines • 4.15 kB
JavaScript
;
/*
* Copyright (c) 2023, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.messageTransformer = void 0;
const ts = require("typescript");
const messages_1 = require("./messages");
/**
*
* @experimental
* transforms `messages` references from dynamic run-time to static compile-time values
*/
const messageTransformer = () => {
messages_1.Messages.importMessagesDirectory(process.cwd());
const transformerFactory = (context) => (sourceFile) => {
if (
// if there are no messages, no transformation is needed
!sourceFile.statements.some((i) => ts.isImportDeclaration(i) && i.importClause?.getText().includes('Messages')) ||
// don't transform the transformer itself
sourceFile.fileName.includes('messageTransformer.ts')) {
return sourceFile;
}
const visitor = (node) => {
if (ts.isExpressionStatement(node) && node.getText().includes('importMessagesDirectory')) {
// importMessagesDirectory now happens at compile, not in runtime
// returning undefined removes the node
return undefined;
}
if (
// transform a runtime load call into hardcoded messages values
// const foo = Messages.load|loadMessages('pluginName', 'messagesFile' ...) =>
// const foo = new Messages('pluginName', 'messagesFile', new Map([['key', 'value']]))
ts.isCallExpression(node) &&
ts.isPropertyAccessExpression(node.expression) &&
node.expression.expression.getText() === 'Messages' &&
node.expression.name.getText().includes('load')) {
// we always want the first two arguments, which are the plugin name and the messages file name
const arrayMembers = node.arguments.slice(0, 2);
const arrayMembersText = arrayMembers.map(getTextWithoutQuotes);
// Messages doesn't care whether you call messages.load or loadMessages, it loads the whole file
const messagesInstance = messages_1.Messages.loadMessages(arrayMembersText[0], arrayMembersText[1]);
return context.factory.createNewExpression(node.expression.expression, undefined, [
arrayMembers[0],
arrayMembers[1],
context.factory.createNewExpression(context.factory.createIdentifier('Map'), undefined, [
messageMapToHardcodedMap(messagesInstance.messages),
]),
]);
}
// it might be a node that contains one of the things we're interested in, so keep digging
return ts.visitEachChild(node, visitor, context);
};
return ts.visitNode(sourceFile, visitor);
};
return transformerFactory;
};
exports.messageTransformer = messageTransformer;
exports.default = exports.messageTransformer;
const getTextWithoutQuotes = (node) => node.getText().replace(/'/g, '');
/** turn a loaded message map into */
const messageMapToHardcodedMap = (messages) => ts.factory.createArrayLiteralExpression(Array.from(messages).map(([key, value]) => {
// case 1: string
if (typeof value === 'string') {
return ts.factory.createArrayLiteralExpression([
ts.factory.createStringLiteral(key),
ts.factory.createStringLiteral(value),
]);
}
else if (Array.isArray(value)) {
// case 2: string[]
return ts.factory.createArrayLiteralExpression([
ts.factory.createStringLiteral(key),
ts.factory.createArrayLiteralExpression(value.map((v) => ts.factory.createStringLiteral(v))),
]);
}
else {
// turn the object into a map and recurse!
return messageMapToHardcodedMap(new Map(Object.entries(value)));
}
}));
//# sourceMappingURL=messageTransformer.js.map