UNPKG

@finos/legend-application

Version:
140 lines 6.91 kB
/** * Copyright (c) 2020-present, Goldman Sachs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { LogEvent, uniq, guaranteeNonEmptyString, DocumentationEntry, } from '@finos/legend-shared'; import { APPLICATION_EVENT } from '../__lib__/LegendApplicationEvent.js'; export const collectKeyedDocumentationEntriesFromConfig = (rawEntries) => Object.entries(rawEntries).map((entry) => ({ key: entry[0], content: DocumentationEntry.create(entry[1], entry[0]), })); export const collectDocumentationLinkEntryFromConfig = (rawEntries) => Object.entries(rawEntries).map((entry) => ({ key: guaranteeNonEmptyString(entry[0], "Documentation link 'key' is missing"), label: guaranteeNonEmptyString(entry[1].label, "Documentation link 'label' is missing"), url: guaranteeNonEmptyString(entry[1].url, "Documentation link 'url' is missing"), })); export const collectContextualDocumentationEntries = (config) => Object.entries(config).map((entry) => ({ context: entry[0], documentationKey: entry[1], })); export class DocumentationService { url; links; docRegistry = new Map(); contextualDocIndex = new Map(); constructor(applicationStore) { // set the main documenation site url this.url = applicationStore.config.documentationUrl; this.links = applicationStore.config.documentationLinkEntries; /** * NOTE: the order of documentation entry overidding is (the later override the former): * 1. Natively specified: specified in the codebase (no overriding allowed within this group of documentation entries): * since we have extension mechanism, the order of plugins matter, * we do not allow overriding, i.e. so the first specification for a documentation key wins * 2. Fetched from documentation registries (no overriding allowed within this group of documentation entries): * since we have extension mechanism and allow specifying multiple registry URLS, * we do not allow overriding, i.e. so the first specification for a documentation key wins * 3. Configured in application config (overiding allowed within this group) */ // build doc registry applicationStore.pluginManager .getApplicationPlugins() .flatMap((plugin) => plugin.getExtraKeyedDocumentationEntries?.() ?? []) .forEach((entry) => { // NOTE: Entries specified natively will not override each other. This is to prevent entries from extensions // accidentally overide entries from core. if (this.hasDocEntry(entry.key)) { applicationStore.logService.warn(LogEvent.create(APPLICATION_EVENT.DOCUMENTATION_LOAD__SKIP), entry.key); } else { this.docRegistry.set(entry.key, entry.content); } }); // entries from config will override entries specified natively applicationStore.config.keyedDocumentationEntries.forEach((entry) => this.docRegistry.set(entry.key, entry.content)); const contextualDocEntries = applicationStore.pluginManager .getApplicationPlugins() .flatMap((plugin) => plugin.getExtraContextualDocumentationEntries?.() ?? []); // verify that required documentations are available const missingDocumentationEntries = []; uniq(applicationStore.pluginManager .getApplicationPlugins() .flatMap((plugin) => plugin.getExtraRequiredDocumentationKeys?.() ?? []) .concat(contextualDocEntries.map((entry) => entry.documentationKey))).forEach((key) => { if (!this.docRegistry.has(key)) { missingDocumentationEntries.push(key); } }); if (missingDocumentationEntries.length) { applicationStore.logService.warn(LogEvent.create(APPLICATION_EVENT.DOCUMENTATION_REQUIREMENT_CHECK__FAILURE), `Can't find corresponding documentation entry for keys:\n${missingDocumentationEntries .map((key) => `- ${key}`) .join('\n')}`); } // Contextual Documentation contextualDocEntries.forEach((entry) => { // NOTE: Entries specified natively will not override each other. This is to prevent entries from extensions // overriding entries from core. // // However, it might be useful to allow extending the list of related doc entries. // This allows extensions to broaden related doc entries for contextual docs // If we need to support this behavior, we could create a dedicated extension method if (this.hasContextualDocEntry(entry.context)) { applicationStore.logService.warn(LogEvent.create(APPLICATION_EVENT.CONTEXTUAL_DOCUMENTATION_LOAD__SKIP), entry.context); } else { const existingDocEntry = this.getDocEntry(entry.documentationKey); if (existingDocEntry) { this.contextualDocIndex.set(entry.context, existingDocEntry); } } }); // entries from config will override entries specified natively applicationStore.config.contextualDocEntries.forEach((entry) => { const existingDocEntry = this.getDocEntry(entry.documentationKey); if (existingDocEntry) { this.contextualDocIndex.set(entry.context, existingDocEntry); } }); } getDocEntry(key) { return this.docRegistry.get(key); } hasDocEntry(key) { return this.docRegistry.has(key); } getContextualDocEntry(key) { return this.contextualDocIndex.get(key); } hasContextualDocEntry(key) { return this.contextualDocIndex.has(key); } getAllDocEntries() { return Array.from(this.docRegistry.values()); } publishDocRegistry() { const result = {}; this.docRegistry.forEach((value, key) => { result[key] = DocumentationEntry.serialization.toJson(value); }); return result; } publishContextualDocIndex() { const result = {}; this.contextualDocIndex.forEach((value, key) => { result[key] = value.key; }); return result; } } //# sourceMappingURL=DocumentationService.js.map