import { isSNScope, type Record } from '@servicenow/sdk-build-core' import { CallExpressionShape, Plugin } from '@servicenow/sdk-build-core' import { generateDeprecatedDiagnostics } from './utils' const roleAliases = { canDelegate: ['can_delegate'], elevatedPrivilege: ['elevated_privilege'], assignableBy: ['assignable_by'], containsRoles: ['contains_roles'], scopedAdmin: ['scoped_admin'], } export const RolePlugin = Plugin.create({ name: 'RolePlugin', records: { sys_user_role: { relationships: { sys_user_role_contains: { via: 'role', descendant: true, relationships: { sys_user_role: { via: 'contains', inverse: true, }, }, }, }, coalesce: ['name'], toShape(record, { descendants }) { return { success: true, value: new CallExpressionShape({ source: record, exportName: record.get('name').ifString()?.getValue(), callee: 'Role', args: [ record .transform(({ $ }) => ({ name: $, assignableBy: $.from('assignable_by').def(''), description: $.def(''), canDelegate: $.from('can_delegate').toBoolean().def(true), elevatedPrivilege: $.from('elevated_privilege').toBoolean().def(false), federatedId: $.from('federated_id').def(''), grantable: $.toBoolean().def(true), scopedAdmin: $.from('scoped_admin').toBoolean().def(false), containsRoles: $.val( descendants .query('sys_user_role_contains') .map((m2m) => m2m.get('contains').toRecordId()) ).def([]), })) .withAliasedKeys(roleAliases), ], }), } }, }, sys_user_role_contains: { coalesce: ['role', 'contains'], }, }, shapes: [ { shape: CallExpressionShape, fileTypes: ['fluent'], async toRecord(callExpression, { config, diagnostics, factory }) { if (callExpression.getCallee() !== 'Role') { return { success: false } } const arg = callExpression.getArgument(0).asObject().withAliasedKeys(roleAliases) generateDeprecatedDiagnostics(arg, diagnostics) const scope = config.scope const name = arg.get('name').asString() if (scope !== 'global' && !isSNScope(scope) && !name.getValue().startsWith(`${scope}.`)) { diagnostics.error(name.getOriginalNode(), `Role name must begin with '${scope}.'`) } const role = await factory.createRecord({ explicitId: arg.get('$id'), source: callExpression, table: 'sys_user_role', properties: arg.transform(({ $ }) => ({ name: $, assignable_by: $.from('assignableBy').def(''), can_delegate: $.from('canDelegate').def(true), description: $.def(''), elevated_privilege: $.from('elevatedPrivilege').def(false), grantable: $.def(true), scoped_admin: $.from('scopedAdmin').def(false), suffix: $.from('name').map((v) => v .asString() .getValue() .replace(new RegExp(`^${config.scope}\\.`), '') ), federated_id: $.from('federatedId').map((v) => v.omitFromXmlIfUndefined()), })), }) const containedRoles: Record[] = [] for (const e of arg.get('containsRoles').ifArray()?.getElements() ?? []) { containedRoles.push( await factory.createRecord({ source: callExpression, table: 'sys_user_role_contains', properties: { role, contains: e.isStringLiteral() ? await factory.createReference({ source: e, table: 'sys_user_role', keys: { name: e }, }) : e, }, }) ) } return { success: true, value: role.with(...(containedRoles ?? [])), } }, }, ], })