import { CallExpressionShape, Plugin, type PropertyAccessShape } from '@servicenow/sdk-build-core' import { NowIdShape } from '../now-id-plugin' import { getUITypeFromId, getUITypeId, APPLIES_TO_CATALOG_ITEM, createScript, createVariablePropertyAccess, getTargetRecord, resolveCatalogReferences, resolveAndValidateVariableId, } from './utils' import { validateCatalogItemVariableSetExclusivity } from './service-catalog-diagnostics' export const CatalogClientScriptPlugin = Plugin.create({ name: 'CatalogClientScriptPlugin', records: { catalog_script_client: { async toShape(record, { database, transform }) { let propertyAccess: PropertyAccessShape | string | undefined if ( record.get('type').asString().getValue() === 'onChange' && !record.get('cat_variable')?.ifString()?.isEmpty() ) { const variableId = record.get('cat_variable').asString()?.getValue()?.replace('IO:', '') const varRecord = database.get('item_option_new', variableId) if (varRecord?.isRecord()) { const appliesToRecord = getTargetRecord(record, database) propertyAccess = (appliesToRecord?.isRecord() && createVariablePropertyAccess(varRecord, record, appliesToRecord)) || variableId } else { propertyAccess = variableId } } const { catalogItemReference, variableSetReference } = resolveCatalogReferences(record, database) const script = await createScript(record, record.get('script'), transform, 'script') return { success: true, value: new CallExpressionShape({ source: record, callee: 'CatalogClientScript', args: [ record.transform(({ $ }) => ({ $id: $.val(NowIdShape.from(record)), name: $, script: $.val(script).def(''), global: $.toBoolean().def(true), active: $.toBoolean().def(true), type: $, uiType: $.from('ui_type') .map((v) => v.ifString()?.isEmpty() ? undefined : getUITypeFromId(v.toNumber()?.getValue()) ) .def('all'), catalogItem: $.val(catalogItemReference).def(''), variableName: $.val(propertyAccess).def(''), variableSet: $.val(variableSetReference).def(''), appliesTo: $.from('applies_to').def(APPLIES_TO_CATALOG_ITEM), appliesOnCatalogItemView: $.from('applies_catalog').toBoolean().def(true), appliesOnRequestedItems: $.from('applies_req_item').toBoolean().def(false), appliesOnCatalogTasks: $.from('applies_sc_task').toBoolean().def(false), appliesOnTargetRecord: $.from('applies_target_record').toBoolean().def(false), vaSupported: $.from('va_supported').toBoolean().def(false), publishedRef: $.from('published_ref').def(''), isolateScript: $.from('isolate_script').toBoolean().def(true), order: $.map((v) => v.ifString()?.ifNotEmpty()?.toNumber()), })), ], }), } }, }, }, shapes: [ { shape: CallExpressionShape, fileTypes: ['fluent'], async toRecord(callExpression, { diagnostics, factory }) { if (callExpression.getCallee() !== 'CatalogClientScript') { return { success: false } } const catalogClientScriptArgs = callExpression.getArgument(0).asObject() // Validate catalogItem and variableSet are mutually exclusive validateCatalogItemVariableSetExclusivity(catalogClientScriptArgs, diagnostics, 'CatalogClientScript') // Check that uiType is 'onChange' only const typeValue = catalogClientScriptArgs.get('type')?.toString()?.getValue() // Handle variableName - extract name and ID from PropertyAccessShape let variableId: string | undefined const appliedTo: 'set' | 'item' = catalogClientScriptArgs.get('appliesTo')?.toString()?.getValue() === 'set' ? 'set' : APPLIES_TO_CATALOG_ITEM if (typeValue && typeValue === 'onChange') { variableId = resolveAndValidateVariableId( catalogClientScriptArgs.get('variableName', false), appliedTo, catalogClientScriptArgs.get('variableSet', false), catalogClientScriptArgs.get('catalogItem', false), diagnostics ) } const record = await factory.createRecord({ source: callExpression, table: 'catalog_script_client', explicitId: catalogClientScriptArgs.get('$id'), properties: catalogClientScriptArgs.transform(({ $ }) => ({ name: $, active: $.def(true), global: $.def(true), script: $.toCdata(), type: $, applies_to: $.from('appliesTo').def(APPLIES_TO_CATALOG_ITEM), cat_item: $.from('catalogItem').def(''), variable_set: $.from('variableSet').def(''), cat_variable: $.val(variableId).def(''), applies_catalog: $.from('appliesOnCatalogItemView').def(true), applies_req_item: $.from('appliesOnRequestedItems').def(false), applies_sc_task: $.from('appliesOnCatalogTasks').def(false), applies_target_record: $.from('appliesOnTargetRecord').def(false), isolate_script: $.from('isolateScript').def(true), order: $.map((v) => v.omitFromXmlWhen((s) => !s.isNumber())), ui_type: $.from('uiType') .map((v) => (v.isString() && !v.isEmpty() ? getUITypeId(v.getValue()) : undefined)) .def(10), va_supported: $.from('vaSupported').toBoolean().def(false), published_ref: $.from('publishedRef').def(''), })), }) return { success: true, value: record } }, }, ], })