UNPKG

@appsemble/node-utils

Version:

NodeJS utilities used by Appsemble internally.

112 lines 5.71 kB
import { defaultLocale, normalizeBlockName } from '@appsemble/lang-sdk'; import { getAppsembleMessages, mergeMessages, } from '@appsemble/node-utils'; import { extractAppMessages } from '@appsemble/utils'; import tags from 'language-tags'; import { assertKoaCondition, throwKoaError } from './koa.js'; export async function getMessagesUtil(ctx, language, appId, merge, { getApp, getAppMessages, getBlockMessages }, override = 'true') { if (!tags.check(language)) { throwKoaError(ctx, 400, '`Language “${language}” is invalid`'); } const lang = language.toLowerCase(); const baseLanguage = tags(language) .subtags() .find((sub) => sub.type() === 'language'); const baseLang = baseLanguage && String(baseLanguage).toLowerCase(); const app = await getApp({ context: ctx, query: { attributes: ['id', 'definition'], where: { id: appId } }, }); assertKoaCondition(app != null, ctx, 404, 'App not found'); const blockPrefixes = []; const blockQuery = []; const blockMessageKeys = new Set(); const extractedMessages = Object.keys(extractAppMessages(app.definition, (block) => { blockMessageKeys.add(`${block.type.startsWith('@') ? block.type : `@appsemble/${block.type}`}-${block.version}`); }).app); const appMessages = (await getAppMessages({ context: ctx, app, language })).map((item) => { const appMsg = item.messages.app ?? {}; const filtered = Object.fromEntries(Object.entries(appMsg).filter(([k]) => { const blockMatch = /^(pages\.[\dA-Za-z-]+(\..+)?)\.blocks\.\d+.+/.test(k); const emailMatch = /emails\.(appInvite|appMemberEmailChange|emailAdded|groupInvite|resend|reset|welcome)\.(body|subject)/.test(k); if (blockMatch || emailMatch) { return true; } return extractedMessages.includes(k); })); return { ...item, messages: { ...item.messages, app: filtered } }; }); const coreMessages = await getAppsembleMessages(lang, baseLang); const messages = { core: Object.fromEntries(Object.entries(coreMessages).filter(([key]) => key.startsWith('app') || key.startsWith('react-components') || key.startsWith('server'))), blocks: {}, ...extractAppMessages(app.definition, (block, prefix) => { const blockName = normalizeBlockName(block.type); const [org, name] = blockName.split('/'); blockQuery.push({ version: block.version, OrganizationId: org.slice(1), name }); blockPrefixes.push([blockName, prefix]); }), }; // @ts-expect-error 2322 null is not assignable to type (strictNullChecks) const blockMessages = await getBlockMessages({ context: ctx, blockQuery, baseLang, lang }); if ((!appMessages.length || (merge && !appMessages.some((m) => m.language === lang))) && lang !== (app.definition.defaultLanguage || defaultLocale)) { throwKoaError(ctx, 404, `Language “${language}” could not be found`); } const filteredMessages = appMessages.map((message) => { // Create a shallow copy of the message to avoid mutating the original const newMessage = message; const filteredBlocks = {}; const blockKeys = Object.keys(newMessage.messages.blocks ?? {}); for (const key of blockKeys) { const block = newMessage.messages.blocks[key]; const filteredBlock = {}; const versionKeys = Object.keys(block); for (const version of versionKeys) { const combinedKey = `${key}-${version}`; if (blockMessageKeys.has(combinedKey)) { filteredBlock[version] = block[version]; } } if (Object.keys(filteredBlock).length > 0) { filteredBlocks[key] = filteredBlock; } } // Assign the filtered blocks back to the new message newMessage.messages.blocks = filteredBlocks; return newMessage; }); const baseLanguageMessages = override === 'true' ? filteredMessages.find((m) => m.language === baseLang) : undefined; const languageMessages = override === 'true' ? filteredMessages.find((m) => m.language === lang) : undefined; for (const block of blockMessages) { const { name } = block; const defaultMessages = block.messages?.[defaultLocale]; const blockBaseLanguageMessages = baseLang && block.messages?.[baseLang]; const blockLanguageMessages = block.messages?.[language]; const blockVersionMessages = { ...defaultMessages, ...Object.fromEntries(Object.entries(blockBaseLanguageMessages ?? {}).filter(([, value]) => value)), ...Object.fromEntries(Object.entries(blockLanguageMessages ?? {}).filter(([, value]) => value)), }; if (messages.blocks[name]) { messages.blocks[name][block.version] = blockVersionMessages; } else { messages.blocks[name] = { [block.version]: blockVersionMessages, }; } if (override !== 'true') { const prefixed = blockPrefixes.filter(([b]) => b === name); for (const [messageId, value] of Object.entries(blockVersionMessages)) { for (const [, prefix] of prefixed) { messages.app[`${prefix.join('.')}.${messageId}`] = value; } } } } return { language: lang, messages: mergeMessages(messages, baseLanguageMessages?.messages ?? {}, languageMessages?.messages ?? {}), }; } //# sourceMappingURL=getMessagesUtil.js.map