import { CallExpressionShape, Plugin, type RecordId } from '@servicenow/sdk-build-core' import { NowIdShape } from './now-id-plugin' /** * Creates an Application Menu (`sys_app_application`). * * @see https://docs.servicenow.com/csh?topicname=app-menu-api-now-ts.html&version=latest * * @param config - an object containing the following properties: * * **$id** - unique id for the record, typically using `Now.ID["value"]` * * **category** - The variable identifier of a menu category that defines the navigation menu style. * * **title** - The label for the menu in the application navigator. * * **active**? - whether the record is enabled * * **description**? - Additional information about what the application does. * * **hint**? - The tooltip text that appears when a user hovers over the menu. * * **name**? - An internal name to differentiate between applications with the same title. * * **order**? - The relative position of the application menu in the application navigator. * * **roles**? - A list of variable identifiers of `Role` objects or names of roles that can access the menu. @see {Role} */ export const ApplicationMenuPlugin = Plugin.create({ name: 'ApplicationMenuPlugin', records: { sys_app_application: { relationships: { sys_app_category: { via: 'category', inverse: true, }, sys_app_application: { via: 'sys_overrides', inverse: true, }, }, async toShape(record, { factory }) { const roles = record.get('roles') const roleNames = roles.ifString()?.ifNotEmpty()?.split(',') ?? [] const roleReferences: RecordId[] = [] for (const roleName of roleNames) { roleReferences.push( await factory.createReference({ source: roles, table: 'sys_user_role', keys: { name: roleName }, }) ) } return { success: true, value: new CallExpressionShape({ source: record, callee: 'ApplicationMenu', exportName: record.get('sys_name')?.ifString()?.getValue(), args: [ record.transform(({ $ }) => ({ $id: $.val(NowIdShape.from(record)), title: $, category: $, hint: $.def(''), description: $.def(''), name: $.def(''), active: $.toBoolean().def(true), order: $.map((v) => v.ifString()?.ifNotEmpty()?.toNumber()).def(100), roles: $.val(roleReferences).def([]), })), ], }), } }, }, }, shapes: [ { shape: CallExpressionShape, fileTypes: ['fluent'], async toRecord(callExpression, { factory }) { if (callExpression.getCallee() !== 'ApplicationMenu') { return { success: false } } const menu = callExpression.getArgument(0).asObject() return { success: true, value: await factory.createRecord({ source: callExpression, table: 'sys_app_application', explicitId: menu.get('$id'), properties: menu.transform(({ $ }) => ({ title: $, hint: $.def(''), description: $.def(''), name: $.def(''), active: $.def(true), order: $.def(100), device_type: $.val('browser'), roles: $.map((v) => v .ifArray() ?.map((r) => (r.ifRecord()?.get('name') ?? r.asString()).getValue()) .join(',') ).def(''), category: $, })), }), } }, }, ], })