UNPKG

powerplatform-mcp

Version:

PowerPlatform Model Context Protocol server

125 lines (124 loc) 6.33 kB
import { readFileSync } from 'node:fs'; import { outputResult } from '../output.js'; export function registerWebResourceCommands(program, registry) { program .command('web-resources') .description('List web resources in a Dataverse environment') .option('--type <n>', 'Filter by web resource type (1=HTML, 2=CSS, 3=JS, 4=XML, 5=PNG, 6=JPG, 7=GIF, 8=Silverlight, 9=StyleSheet, 10=ICO, 11=Vector, 12=SVG)') .option('--name <contains>', 'Filter web resources whose name contains this string') .option('--max <n>', 'Maximum number of records to return', '100') .action(async (opts, command) => { const ctx = registry.getContext(command.optsWithGlobals().env); const service = ctx.getWebResourceService(); const result = await service.getWebResources({ maxRecords: parseInt(opts.max, 10), webResourceType: opts.type ? parseInt(opts.type, 10) : undefined, nameFilter: opts.name, }); const resources = result.value || []; const topItems = resources .slice(0, 10) .map((r) => ` ${r.name} (type: ${r.webresourcetype})`) .join('\n'); outputResult({ fileName: 'web-resources', data: result, summary: [ `Found ${resources.length} web resources.`, resources.length > 0 ? topItems : '', resources.length > 10 ? ` + ${resources.length - 10} more in file` : '', ].filter(Boolean).join('\n'), }, ctx.environmentName); }); program .command('web-resource <name>') .description('Get a single web resource by its exact name') .action(async (name, _opts, command) => { const ctx = registry.getContext(command.optsWithGlobals().env); const service = ctx.getWebResourceService(); const webResource = await service.getWebResource(name); if (!webResource) { console.log(`Web resource '${name}' not found.`); return; } outputResult({ fileName: `web-resource-${name.replace(/[/\\]/g, '_')}`, data: webResource, summary: [ `Web Resource: ${webResource.name}`, ` Display Name: ${webResource.displayname ?? 'N/A'}`, ` Type: ${webResource.webresourcetype}`, ` Is Managed: ${webResource.ismanaged}`, ` Modified On: ${webResource.modifiedon}`, webResource.description ? ` Description: ${webResource.description}` : '', ].filter(Boolean).join('\n'), }, ctx.environmentName); }); program .command('create-web-resource <name> <displayName> <filePath>') .description('Create a new web resource by uploading a file') .option('--type <n>', 'Web resource type (1=HTML, 2=CSS, 3=JS, 4=XML, 5=PNG, 6=JPG, 7=GIF, 8=Silverlight, 9=StyleSheet, 10=ICO, 11=Vector, 12=SVG)', '3') .option('--description <desc>', 'Description for the web resource') .option('--solution <name>', 'Solution unique name to add the component to') .action(async (name, displayName, filePath, opts, command) => { const ctx = registry.getContext(command.optsWithGlobals().env); const service = ctx.getWebResourceService(); const fileContent = readFileSync(filePath); const base64Content = Buffer.from(fileContent).toString('base64'); const result = await service.createWebResource({ name, displayName, webResourceType: parseInt(opts.type, 10), content: base64Content, description: opts.description, solutionName: opts.solution, }); outputResult({ fileName: `create-web-resource-${name.replace(/[/\\]/g, '_')}`, data: result, summary: [ `Created web resource '${name}':`, ` Display Name: ${displayName}`, ` Type: ${opts.type}`, ` File: ${filePath}`, ` Web Resource ID: ${result.webResourceId}`, ].join('\n'), }, ctx.environmentName); }); program .command('set-entity-icon <entityName> <svgFilePath>') .description('Upload an SVG (or reuse existing) and set it as the entity icon in Dataverse') .option('--solution <name>', 'Solution unique name to add the webresource/entity to', 'borsocore') .option('--web-resource-name <name>', 'Web resource logical name (default: <entity>_icon.svg)') .option('--display-name <name>', 'Display name for the web resource (default: derived from entity)') .option('--no-publish', 'Skip publishing customizations after setting the icon') .action(async (entityName, svgFilePath, opts, command) => { const ctx = registry.getContext(command.optsWithGlobals().env); const webResourceService = ctx.getWebResourceService(); const entityService = ctx.getEntityService(); const solutionService = ctx.getSolutionService(); const name = opts.webResourceName ?? `${entityName}_icon.svg`; const displayName = opts.displayName ?? `${entityName} icon`; const base64 = Buffer.from(readFileSync(svgFilePath)).toString('base64'); const { webResourceId, created } = await webResourceService.upsertWebResource({ name, displayName, webResourceType: 11, content: base64, solutionName: opts.solution, }); await entityService.setEntityIconVector(entityName, name, opts.solution); if (opts.publish !== false) { await solutionService.publishCustomizations(entityName); } outputResult({ fileName: `set-entity-icon-${entityName}`, data: { webResourceId, webResourceName: name, entityName, created }, summary: [ `${created ? 'Created' : 'Updated'} web resource '${name}' (id: ${webResourceId})`, `Set ${entityName}.IconVectorName = '${name}'`, opts.publish !== false ? `Published customizations for '${entityName}'` : 'Skipped publish', ].join('\n'), }, ctx.environmentName); }); }