UNPKG

@alfresco/adf-extensions

Version:

Provides extensibility support for ADF applications.

1 lines 97.5 kB
{"version":3,"file":"adf-extensions.mjs","sources":["../../../../lib/extensions/src/lib/config/action.extensions.ts","../../../../lib/extensions/src/lib/config/document-list.extensions.ts","../../../../lib/extensions/src/lib/config/extension-element.ts","../../../../lib/extensions/src/lib/config/extension-utils.ts","../../../../lib/extensions/src/lib/config/extension.config.ts","../../../../lib/extensions/src/lib/config/icon.extensions.ts","../../../../lib/extensions/src/lib/config/navbar.extensions.ts","../../../../lib/extensions/src/lib/config/permission.extensions.ts","../../../../lib/extensions/src/lib/config/routing.extensions.ts","../../../../lib/extensions/src/lib/config/rule.extensions.ts","../../../../lib/extensions/src/lib/config/sidebar.extensions.ts","../../../../lib/extensions/src/lib/config/viewer.extensions.ts","../../../../lib/extensions/src/lib/services/extension-loader.service.ts","../../../../lib/extensions/src/lib/evaluators/core.evaluators.ts","../../../../lib/extensions/src/lib/services/component-register.service.ts","../../../../lib/extensions/src/lib/services/rule.service.ts","../../../../lib/extensions/src/lib/services/extension.service.ts","../../../../lib/extensions/src/lib/services/app-extension.service.ts","../../../../lib/extensions/src/lib/store/states/navigation.state.ts","../../../../lib/extensions/src/lib/store/states/profile.state.ts","../../../../lib/extensions/src/lib/store/states/selection.state.ts","../../../../lib/extensions/src/lib/store/states/repository.state.ts","../../../../lib/extensions/src/lib/components/viewer/viewer-extension.interface.ts","../../../../lib/extensions/src/lib/components/viewer/preview-extension.component.ts","../../../../lib/extensions/src/lib/components/dynamic-column/dynamic-column.component.ts","../../../../lib/extensions/src/lib/components/dynamic-component/dynamic.component.ts","../../../../lib/extensions/src/lib/components/dynamic-tab/dynamic-tab.component.ts","../../../../lib/extensions/src/lib/components/public-api.ts","../../../../lib/extensions/src/lib/extensions.module.ts","../../../../lib/extensions/src/lib/providers.ts","../../../../lib/extensions/src/public-api.ts","../../../../lib/extensions/src/adf-extensions.ts"],"sourcesContent":["/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ExtensionElement } from './extension-element';\n\n// eslint-disable-next-line no-shadow\nexport enum ContentActionType {\n default = 'default',\n button = 'button',\n separator = 'separator',\n menu = 'menu',\n custom = 'custom'\n}\n\nexport interface ContentActionRef extends ExtensionElement {\n type: ContentActionType;\n\n title?: string;\n tooltip?: string;\n description?: string;\n icon?: string;\n children?: Array<ContentActionRef>;\n component?: string;\n data?: any;\n color?: string;\n actions?: {\n [key: string]: string;\n click?: string;\n };\n rules?: {\n [key: string]: string;\n enabled?: string;\n visible?: string;\n };\n}\n\nexport interface ActionRef {\n id: string;\n type: string;\n payload?: any;\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* eslint-disable id-blacklist */\n\nimport { ExtensionElement } from './extension-element';\n\nexport interface DataColumnTypes {\n text: string;\n image: string;\n date: string;\n json: string;\n icon: string;\n fileSize: string;\n location: string;\n boolean: string;\n amount: string;\n number: string;\n}\n\nexport type DataColumnType = keyof DataColumnTypes;\n\nexport interface DocumentListPresetRef extends ExtensionElement {\n key: string;\n type: DataColumnType;\n title?: string;\n format?: string;\n class?: string;\n sortable: boolean;\n template: string;\n desktopOnly: boolean;\n sortingKey: string;\n isHidden?: boolean;\n rules?: {\n [key: string]: string;\n visible?: string;\n };\n draggable?: boolean;\n resizable?: boolean;\n maxTextLength?: number;\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport interface ExtensionElement {\n id: string;\n\n order?: number;\n disabled?: boolean;\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ContentActionRef, ContentActionType } from './action.extensions';\n\nexport const getValue = (target: any, key: string): any => {\n if (!target) {\n return undefined;\n }\n\n const keys = key.split('.');\n key = '';\n\n do {\n key += keys.shift();\n const value = target[key];\n if (\n value !== undefined &&\n (typeof value === 'object' || !keys.length)\n ) {\n target = value;\n key = '';\n } else if (!keys.length) {\n target = undefined;\n } else {\n key += '.';\n }\n } while (keys.length);\n\n return target;\n};\n\nexport const filterEnabled = (entry: { disabled?: boolean }): boolean => !entry.disabled;\n\nexport const sortByOrder = (\n a: { order?: number | undefined },\n b: { order?: number | undefined }\n) => {\n const left = a.order === undefined ? Number.MAX_SAFE_INTEGER : a.order;\n const right = b.order === undefined ? Number.MAX_SAFE_INTEGER : b.order;\n return left - right;\n};\n\nexport const reduceSeparators = (\n acc: ContentActionRef[],\n el: ContentActionRef,\n i: number,\n arr: ContentActionRef[]\n): ContentActionRef[] => {\n // remove leading separator\n if (i === 0) {\n if (arr[i].type === ContentActionType.separator) {\n return acc;\n }\n }\n // remove duplicate separators\n if (i > 0) {\n const prev = arr[i - 1];\n if (\n prev.type === ContentActionType.separator &&\n el.type === ContentActionType.separator\n ) {\n return acc;\n }\n\n // remove trailing separator\n if (i === arr.length - 1) {\n if (el.type === ContentActionType.separator) {\n return acc;\n }\n }\n }\n\n return acc.concat(el);\n};\n\nexport const reduceEmptyMenus = (\n acc: ContentActionRef[],\n el: ContentActionRef\n): ContentActionRef[] => {\n if (el.type === ContentActionType.menu) {\n if ((el.children || []).length === 0) {\n return acc;\n }\n }\n return acc.concat(el);\n};\n\nexport const mergeObjects = (...objects: any[]): any => {\n const result = {};\n\n objects.forEach((source) => {\n Object.keys(source).forEach((prop) => {\n let replace = false;\n\n if (prop.endsWith('.$replace')) {\n replace = true;\n prop = prop.replace('.$replace', '');\n }\n\n if (!prop.startsWith('$')) {\n if (replace) {\n result[prop] = source[`${prop}.$replace`];\n } else if (prop in result && Array.isArray(result[prop])) {\n if (Array.isArray(source[prop])) {\n result[prop] = mergeArrays(result[prop], source[prop]);\n } else {\n result[prop] = [...result[prop], source[prop]];\n }\n } else if (prop in result && typeof result[prop] === 'object') {\n result[prop] = mergeObjects(result[prop], source[prop]);\n } else {\n result[prop] = source[prop];\n }\n }\n });\n });\n\n return result;\n};\n\nexport const mergeArrays = (left: any[], right: any[]): any[] => {\n const result = [];\n const map = {};\n\n (left || []).forEach((entry) => {\n const element = entry;\n if (element && Object.prototype.hasOwnProperty.call(element, 'id')) {\n map[element.id] = element;\n } else {\n result.push(element);\n }\n });\n\n (right || []).forEach((entry) => {\n const element = entry;\n if (element && Object.prototype.hasOwnProperty.call(element, 'id') && map[element.id]) {\n const merged = mergeObjects(map[element.id], element);\n map[element.id] = merged;\n } else {\n result.push(element);\n }\n });\n\n return Object.keys(map).map((key) => map[key]).concat(result);\n};\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { RouteRef } from './routing.extensions';\nimport { RuleRef } from './rule.extensions';\nimport { ActionRef } from './action.extensions';\n\nexport interface ExtensionRef {\n $id: string;\n $name: string;\n $version: string;\n $vendor: string;\n $license: string;\n $runtime?: string;\n $description?: string;\n $dependencies?: Array<string>;\n\n appConfig?: any;\n rules?: Array<RuleRef>;\n routes?: Array<RouteRef>;\n actions?: Array<ActionRef>;\n\n features?: {\n [key: string]: any;\n };\n}\n\nexport interface ExtensionConfig extends ExtensionRef {\n $references?: Array<string | ExtensionRef>;\n $ignoreReferenceList?: Array<string>;\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ExtensionElement } from './extension-element';\n\nexport interface IconRef extends ExtensionElement {\n value: string;\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ExtensionElement } from './extension-element';\n\nexport interface NavBarRules {\n [ruleId: string]: string;\n}\n\nexport interface NavBarGroupRef extends ExtensionElement {\n items: Array<NavBarLinkRef>;\n rules?: NavBarRules;\n}\n\nexport interface NavBarLinkRef extends ExtensionElement {\n icon: string;\n title: string;\n route: string;\n\n provider?: string;\n component?: string;\n url?: string; // evaluated at runtime based on route ref\n description?: string;\n children?: Array<NavBarLinkRef>;\n rules?: NavBarRules;\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport interface NodePermissions {\n check(source: any, permissions: string[], options?: any): boolean;\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport interface RouteRef {\n id: string;\n path: string;\n component: string;\n parentRoute?: string;\n layout?: string;\n auth?: string[];\n data?: { [key: string]: string };\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { SelectionState } from '../store/states/selection.state';\nimport { NavigationState } from '../store/states/navigation.state';\nimport { NodePermissions } from './permission.extensions';\nimport { ProfileState } from '../store/states/profile.state';\nimport { RepositoryInfo } from '@alfresco/js-api';\n\nexport type RuleEvaluator = (context: RuleContext, ...args: any[]) => boolean;\n\nexport interface RuleContext {\n repository: RepositoryInfo;\n auth: any;\n selection: SelectionState;\n navigation: NavigationState;\n profile: ProfileState;\n permissions: NodePermissions;\n\n getEvaluator(key: string): RuleEvaluator;\n}\n\nexport class RuleRef {\n type: string;\n id?: string;\n parameters?: Array<RuleParameter>;\n}\n\nexport interface RuleParameter {\n type: string;\n value: any;\n parameters?: Array<RuleParameter>;\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ExtensionElement } from './extension-element';\n\nexport interface SidebarTabRef extends ExtensionElement {\n title: string;\n component: string;\n\n icon?: string;\n rules?: {\n [key: string]: string;\n visible?: string;\n };\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ExtensionElement } from './extension-element';\n\nexport interface ViewerExtensionRef extends ExtensionElement {\n fileExtension: string;\n component: string;\n\n rules?: {\n [key: string]: string;\n visible?: string;\n };\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { HttpClient } from '@angular/common/http';\nimport { Injectable } from '@angular/core';\nimport { ActionRef, ContentActionRef, ContentActionType } from '../config/action.extensions';\nimport { ExtensionElement } from '../config/extension-element';\nimport { filterEnabled, getValue, mergeObjects, sortByOrder } from '../config/extension-utils';\nimport { ExtensionConfig, ExtensionRef } from '../config/extension.config';\nimport { RouteRef } from '../config/routing.extensions';\nimport { RuleRef } from '../config/rule.extensions';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ExtensionLoaderService {\n constructor(private http: HttpClient) {}\n\n load(configPath: string, pluginsPath: string, extensions?: string[], extensionValues?: ExtensionConfig[]): Promise<ExtensionConfig> {\n return new Promise<any>((resolve) => {\n this.loadConfig(configPath, 0).then((result) => {\n if (result) {\n let config = result.config;\n\n const override = sessionStorage.getItem('app.extension.config');\n if (override) {\n config = JSON.parse(override);\n }\n\n if (!config.$references?.length) {\n config.$references = this.filterIgnoredExtensions(extensions || [], config.$ignoreReferenceList);\n } else {\n config.$references = this.filterIgnoredExtensions(config.$references, config.$ignoreReferenceList);\n }\n\n if (config.$references?.length > 0 || extensionValues) {\n const plugins = (config.$references ?? []).map((name, idx) => this.loadConfig(`${pluginsPath}/${name}`, idx));\n\n Promise.all(plugins).then((results) => {\n let configs = results\n .filter((entry) => entry)\n .sort(sortByOrder)\n .map((entry) => entry.config);\n\n if (extensionValues) {\n configs = [...configs, ...extensionValues];\n }\n\n if (configs.length > 0) {\n config = mergeObjects(config, ...configs);\n }\n\n config = {\n ...config,\n ...this.getMetadata(result.config),\n $references: configs.map((ext) => this.getMetadata(ext))\n };\n\n resolve(config);\n });\n } else {\n resolve(config);\n }\n }\n });\n });\n }\n\n /**\n * Retrieves configuration elements.\n * Filters element by **enabled** and **order** attributes.\n * Example:\n * `getElements<ViewerExtensionRef>(config, 'features.viewer.extensions')`\n * @param config configuration settings\n * @param key element key\n * @param fallback fallback array of values\n * @returns list of elements\n */\n getElements<T extends ExtensionElement>(config: ExtensionConfig, key: string, fallback: Array<T> = []): Array<T> {\n const values = getValue(config, key) || fallback || [];\n return values.filter(filterEnabled).sort(sortByOrder);\n }\n\n getContentActions(config: ExtensionConfig, key: string): Array<ContentActionRef> {\n return this.getElements(config, key).map(this.setActionDefaults);\n }\n\n getRules(config: ExtensionConfig): Array<RuleRef> {\n if (config?.rules) {\n return config.rules;\n }\n return [];\n }\n\n getRoutes(config: ExtensionConfig): Array<RouteRef> {\n if (config) {\n return config.routes || [];\n }\n return [];\n }\n\n getActions(config: ExtensionConfig): Array<ActionRef> {\n if (config) {\n return config.actions || [];\n }\n return [];\n }\n\n getFeatures(config: ExtensionConfig): any {\n if (config) {\n return config.features || [];\n }\n return [];\n }\n\n protected getMetadata(config: ExtensionConfig): ExtensionRef {\n const result: any = {};\n\n Object.keys(config)\n .filter((key) => key.startsWith('$'))\n .forEach((key) => {\n result[key] = config[key];\n });\n\n return result;\n }\n\n protected loadConfig(url: string, order: number): Promise<{ order: number; config: ExtensionConfig }> {\n return new Promise((resolve) => {\n this.http.get<ExtensionConfig>(url).subscribe(\n (config) => {\n resolve({\n order,\n config\n });\n },\n () => {\n resolve(null);\n }\n );\n });\n }\n\n protected setActionDefaults(action: ContentActionRef): ContentActionRef {\n if (action) {\n action.type = action.type || ContentActionType.default;\n action.icon = action.icon || 'extension';\n }\n return action;\n }\n\n private filterIgnoredExtensions(extensions: Array<string | ExtensionRef>, ignoreReferenceList: string[]): Array<string | ExtensionRef> {\n if (!ignoreReferenceList?.length) {\n return extensions;\n }\n\n return extensions.map((file: string) => file.match('(?!.*/).+')[0]).filter((fileName: string) => !ignoreReferenceList.includes(fileName));\n }\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { RuleContext, RuleParameter } from '../config/rule.extensions';\n\nexport const not = (context: RuleContext, ...args: RuleParameter[]): boolean => {\n if (!args || args.length === 0) {\n return false;\n }\n\n return args\n .every((arg) => {\n const evaluator = context.getEvaluator(arg.value);\n if (!evaluator) {\n console.warn('evaluator not found: ' + arg.value);\n return false;\n }\n return !evaluator(context, ...(arg.parameters || []));\n });\n};\n\nexport const every = (context: RuleContext, ...args: RuleParameter[]): boolean => {\n if (!args || args.length === 0) {\n return false;\n }\n\n return args\n .every((arg) => {\n const evaluator = context.getEvaluator(arg.value);\n if (!evaluator) {\n console.warn('evaluator not found: ' + arg.value);\n return false;\n }\n return evaluator(context, ...(arg.parameters || []));\n });\n};\n\nexport const some = (context: RuleContext, ...args: RuleParameter[]): boolean => {\n if (!args || args.length === 0) {\n return false;\n }\n\n return args\n .some((arg) => {\n const evaluator = context.getEvaluator(arg.value);\n if (!evaluator) {\n console.warn('evaluator not found: ' + arg.value);\n return false;\n }\n return evaluator(context, ...(arg.parameters || []));\n });\n};\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Injectable, Type } from '@angular/core';\nimport { MatMenuItem } from '@angular/material/menu';\n\nexport interface ExtensionComponent {\n data: any;\n menuItem?: MatMenuItem;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class ComponentRegisterService {\n components: Record<string, Type<any>> = {};\n\n setComponents(values: Record<string, Type<any>>) {\n if (values) {\n this.components = Object.assign({}, this.components, values);\n }\n }\n\n getComponentById<T>(id: string): Type<T> {\n return this.components[id];\n }\n\n hasComponentById(id: string): boolean {\n return !!this.getComponentById(id);\n }\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Injectable } from '@angular/core';\nimport { RuleRef, RuleContext, RuleEvaluator, RuleParameter } from '../config/rule.extensions';\nimport { ExtensionConfig } from '../config/extension.config';\nimport { ExtensionLoaderService } from './extension-loader.service';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class RuleService {\n context: RuleContext = null;\n rules: Array<RuleRef> = [];\n evaluators: { [key: string]: RuleEvaluator } = {};\n\n constructor(protected loader: ExtensionLoaderService) {}\n\n setup(config: ExtensionConfig) {\n this.rules = this.loader.getRules(config);\n }\n\n /**\n * Adds one or more new rule evaluators to the existing set.\n * @param values The new evaluators to add\n */\n setEvaluators(values: Record<string, RuleEvaluator>) {\n if (values) {\n this.evaluators = Object.assign({}, this.evaluators, values);\n }\n }\n\n /**\n * Retrieves a rule using its ID value.\n * @param id The ID value to look for\n * @returns The rule or null if not found\n */\n getRuleById(id: string): RuleRef {\n return this.rules.find((ref) => ref.id === id);\n }\n\n /**\n * Retrieves a RuleEvaluator function using its key name.\n * @param key Key name to look for\n * @returns RuleEvaluator or null if not found\n */\n getEvaluator(key: string): RuleEvaluator {\n if (key?.startsWith('!')) {\n const fn = this.evaluators[key.substring(1)];\n return (context: RuleContext, ...args: RuleParameter[]): boolean => !fn(context, ...args);\n }\n return this.evaluators[key];\n }\n\n /**\n * Evaluates a rule.\n * @param ruleId ID of the rule to evaluate\n * @param context Custom rule execution context.\n * @returns True if the rule passed, false otherwise\n */\n evaluateRule(ruleId: string, context?: RuleContext): boolean {\n const ruleRef = this.getRuleById(ruleId);\n context = context || this.context;\n\n if (ruleRef) {\n const evaluator = this.getEvaluator(ruleRef.type);\n if (evaluator) {\n return evaluator(context, ...ruleRef.parameters);\n }\n } else {\n const evaluator = this.getEvaluator(ruleId);\n if (evaluator) {\n return evaluator(context);\n }\n }\n return false;\n }\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Injectable, Type, InjectionToken, Inject } from '@angular/core';\nimport { RuleEvaluator, RuleRef, RuleContext } from '../config/rule.extensions';\nimport { ExtensionConfig } from '../config/extension.config';\nimport { ExtensionLoaderService } from './extension-loader.service';\nimport { RouteRef } from '../config/routing.extensions';\nimport { ActionRef } from '../config/action.extensions';\nimport * as core from '../evaluators/core.evaluators';\nimport { ComponentRegisterService } from './component-register.service';\nimport { RuleService } from './rule.service';\nimport { ExtensionElement } from '../config/extension-element';\nimport { BehaviorSubject, Observable } from 'rxjs';\n\n/**\n * The default extensions factory\n * @returns the list of extension json files\n */\nexport function extensionJsonsFactory() {\n return [];\n}\n\nexport const EXTENSION_JSONS = new InjectionToken<string[][]>('extension-jsons', {\n providedIn: 'root',\n factory: extensionJsonsFactory\n});\n\nexport const EXTENSION_JSON_VALUES = new InjectionToken<string[][]>('extension-jsons-values', {\n providedIn: 'root',\n factory: extensionJsonsFactory\n});\n\n/**\n * Provides the extension json values for the angular modules\n * @param jsons files to provide\n * @returns a provider section\n */\nexport function provideExtensionConfig(jsons: string[]) {\n return {\n provide: EXTENSION_JSONS,\n useValue: jsons,\n multi: true\n };\n}\n\n/**\n * Provides the extension json raw values for the angular modules\n * @param extensionConfigValue config value\n * @returns a provider section\n */\nexport function provideExtensionConfigValues(extensionConfigValue: ExtensionConfig[]) {\n return {\n provide: EXTENSION_JSON_VALUES,\n useValue: extensionConfigValue,\n multi: true\n };\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ExtensionService {\n configPath = 'assets/app.extensions.json';\n pluginsPath = 'assets/plugins';\n\n routes: Array<RouteRef> = [];\n actions: Array<ActionRef> = [];\n features: Array<any> = [];\n authGuards: Record<string, unknown> = {};\n\n setup$: Observable<ExtensionConfig>;\n\n protected config: ExtensionConfig = null;\n protected onSetup$ = new BehaviorSubject<ExtensionConfig>(this.config);\n\n constructor(\n protected loader: ExtensionLoaderService,\n protected componentRegister: ComponentRegisterService,\n protected ruleService: RuleService,\n @Inject(EXTENSION_JSONS) protected extensionJsons: string[],\n @Inject(EXTENSION_JSON_VALUES) protected extensionJsonValues: ExtensionConfig[]\n ) {\n this.setup$ = this.onSetup$.asObservable();\n }\n\n /**\n * Loads and registers an extension config file and plugins (specified by path properties).\n * @returns The loaded config data\n */\n async load(): Promise<ExtensionConfig> {\n const config = await this.loader.load(this.configPath, this.pluginsPath, this.extensionJsons.flat(), this.extensionJsonValues.flat());\n\n this.setup(config);\n return config;\n }\n\n /**\n * Registers extensions from a config object.\n * @param config Object with config data\n */\n setup(config: ExtensionConfig) {\n if (!config) {\n console.warn('Extension configuration not found');\n return;\n }\n\n this.config = config;\n\n this.setEvaluators({\n 'core.every': core.every,\n 'core.some': core.some,\n 'core.not': core.not\n });\n\n this.actions = this.loader.getActions(config);\n this.routes = this.loader.getRoutes(config);\n this.features = this.loader.getFeatures(config);\n\n this.ruleService.setup(config);\n this.onSetup$.next(config);\n }\n\n /**\n * Gets features by key.\n * @param key Key string using dot notation or array of strings\n * @param defaultValue Default value returned if feature is not found, default is empty array\n * @returns Feature found by key\n */\n getFeature<T = any[]>(key: string | string[], defaultValue: any = []): T {\n const properties: string[] = Array.isArray(key) ? key : key.split('.');\n return properties.reduce((prev, curr) => prev?.[curr], this.features) || defaultValue;\n }\n\n getElements<T extends ExtensionElement>(key: string, fallback: Array<T> = []): Array<T> {\n return this.loader.getElements(this.config, key, fallback);\n }\n\n /**\n * Adds one or more new rule evaluators to the existing set.\n * @param values The new evaluators to add\n */\n setEvaluators(values: Record<string, RuleEvaluator>) {\n this.ruleService.setEvaluators(values);\n }\n\n /**\n * Adds one or more new auth guards to the existing set.\n * @param values The new auth guards to add\n */\n setAuthGuards(values: Record<string, unknown>) {\n if (values) {\n this.authGuards = Object.assign({}, this.authGuards, values);\n }\n }\n\n /**\n * Adds one or more new components to the existing set.\n * @param values The new components to add\n */\n setComponents(values: Record<string, Type<any>>) {\n this.componentRegister.setComponents(values);\n }\n\n /**\n * Retrieves a route using its ID value.\n * @param id The ID value to look for\n * @returns The route or null if not found\n */\n getRouteById(id: string): RouteRef {\n return this.routes.find((route) => route.id === id);\n }\n\n /**\n * Retrieves one or more auth guards using an array of ID values.\n * @param ids Array of ID value to look for\n * @returns Array of auth guards or empty array if none were found\n */\n getAuthGuards(ids: string[]): Array<unknown> {\n return (ids || []).map((id) => this.authGuards[id]).filter((guard) => guard);\n }\n\n /**\n * Retrieves an action using its ID value.\n * @param id The ID value to look for\n * @returns Action or null if not found\n */\n getActionById(id: string): ActionRef {\n return this.actions.find((action) => action.id === id);\n }\n\n /**\n * Retrieves a RuleEvaluator function using its key name.\n * @param key Key name to look for\n * @returns RuleEvaluator or null if not found\n */\n getEvaluator(key: string): RuleEvaluator {\n return this.ruleService.getEvaluator(key);\n }\n\n /**\n * Evaluates a rule.\n * @param ruleId ID of the rule to evaluate\n * @param context Custom rule execution context.\n * @returns True if the rule passed, false otherwise\n */\n evaluateRule(ruleId: string, context?: RuleContext): boolean {\n return this.ruleService.evaluateRule(ruleId, context);\n }\n\n /**\n * Retrieves a registered extension component using its ID value.\n * @param id The ID value to look for\n * @returns The component or null if not found\n */\n getComponentById<T>(id: string) {\n return this.componentRegister.getComponentById<T>(id);\n }\n\n /**\n * Retrieves a rule using its ID value.\n * @param id The ID value to look for\n * @returns The rule or null if not found\n */\n getRuleById(id: string): RuleRef {\n return this.ruleService.getRuleById(id);\n }\n\n /**\n * Runs a lightweight expression stored in a string.\n * @param value String containing the expression or literal value\n * @param context Parameter object for the expression with details of app state\n * @returns Result of evaluated expression, if found, or the literal value otherwise\n */\n runExpression(value: string | any, context?: any) {\n if (typeof value === 'string') {\n return this.evaluateExpression(value, context);\n } else {\n const duplicate = Object.assign({}, value);\n Object.keys(duplicate).forEach((key) => {\n duplicate[key] = this.evaluateExpression(duplicate[key], context);\n });\n return duplicate;\n }\n }\n\n private evaluateExpression(value: string, context?: any): string {\n const pattern = new RegExp(/\\$\\((.*\\)?)\\)/g);\n const matches = pattern.exec(value);\n\n if (matches && matches.length > 1) {\n const expression = matches[1];\n const fn = new Function('context', `return ${expression}`);\n const result = fn(context);\n\n return result;\n }\n return value;\n }\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Injectable } from '@angular/core';\nimport { ExtensionConfig, ExtensionRef } from '../config/extension.config';\nimport { ExtensionService } from '../services/extension.service';\nimport { Observable, BehaviorSubject } from 'rxjs';\nimport { ViewerExtensionRef } from '../config/viewer.extensions';\nimport { DocumentListPresetRef } from '../config/document-list.extensions';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class AppExtensionService {\n references$: Observable<ExtensionRef[]>;\n private _references = new BehaviorSubject<ExtensionRef[]>([]);\n\n constructor(protected extensionService: ExtensionService) {\n this.references$ = this._references.asObservable();\n }\n\n async load() {\n const config = await this.extensionService.load();\n this.setup(config);\n }\n\n setup(config: ExtensionConfig) {\n if (!config) {\n return;\n }\n\n const references = (config.$references || []).filter((entry) => typeof entry === 'object').map((entry) => entry as ExtensionRef);\n this._references.next(references);\n }\n\n /**\n * Provides a collection of document list columns for the particular preset.\n * The result is filtered by the **disabled** state.\n * @param key Preset key.\n * @returns list of document list presets\n */\n getDocumentListPreset(key: string): DocumentListPresetRef[] {\n return this.extensionService.getElements<DocumentListPresetRef>(`features.documentList.${key}`).filter((entry) => !entry.disabled);\n }\n\n /**\n * Provides a list of the Viewer content extensions,\n * filtered by **disabled** state and **rules**.\n * @returns list of viewer extension references\n */\n getViewerExtensions(): ViewerExtensionRef[] {\n return this.extensionService\n .getElements<ViewerExtensionRef>('features.viewer.extensions')\n .filter((extension) => !this.isViewerExtensionDisabled(extension));\n }\n\n protected isViewerExtensionDisabled(extension: ViewerExtensionRef): boolean {\n if (extension) {\n if (extension.disabled) {\n return true;\n }\n\n if (extension.rules?.disabled) {\n return this.extensionService.evaluateRule(extension.rules.disabled);\n }\n }\n\n return false;\n }\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Node } from '@alfresco/js-api';\n\nexport interface NavigationState {\n currentFolder?: Node;\n url?: string;\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Group } from '@alfresco/js-api';\n\nexport interface ProfileState {\n [key: string]: any;\n\n id: string;\n isAdmin: boolean;\n firstName: string;\n lastName: string;\n userName?: string;\n initials?: string;\n groups?: Group[];\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { NodeEntry, SiteEntry } from '@alfresco/js-api';\n\nexport interface SelectionState {\n count: number;\n nodes: NodeEntry[];\n libraries: SiteEntry[];\n isEmpty: boolean;\n first?: NodeEntry;\n last?: NodeEntry;\n folder?: NodeEntry;\n file?: NodeEntry;\n library?: SiteEntry;\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport interface RepositoryState {\n isAuditEnabled?: boolean;\n isQuickShareEnabled?: boolean;\n isReadOnly?: boolean;\n isThumbnailGenerationEnabled?: boolean;\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Node } from '@alfresco/js-api';\n\nexport interface ViewerExtensionInterface {\n url: string;\n nameFile: string;\n node: Node;\n}\n","/*!\n * @license\n * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.\n *\n * Li