From 0efa415a0c285617336b7171b11486093fd87e02 Mon Sep 17 00:00:00 2001 From: aman06it <36499868+aman06it@users.noreply.github.com> Date: Fri, 22 May 2026 16:08:35 +0530 Subject: [PATCH] feat: add microfrontend template generator command Exposes `sf template generate microfrontend` to scaffold a microfrontend LWC bundle, paired with the new generator in salesforcedx-templates. --- command-snapshot.json | 19 ++++ messages/microfrontend.md | 51 +++++++++++ .../template/generate/microfrontend.ts | 89 +++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 messages/microfrontend.md create mode 100644 src/commands/template/generate/microfrontend.ts diff --git a/command-snapshot.json b/command-snapshot.json index 2d0b1663..af08956c 100644 --- a/command-snapshot.json +++ b/command-snapshot.json @@ -103,6 +103,25 @@ "flags": ["api-version", "flags-dir", "internal", "json", "loglevel", "name", "output-dir", "template"], "plugin": "@salesforce/plugin-templates" }, + { + "alias": [], + "command": "template:generate:microfrontend", + "flagAliases": ["apiversion", "outputdir"], + "flagChars": ["d", "i", "n", "s"], + "flags": [ + "api-version", + "flags-dir", + "internal", + "json", + "loglevel", + "name", + "output-dir", + "sandbox", + "shell-title", + "src" + ], + "plugin": "@salesforce/plugin-templates" + }, { "alias": ["force:project:create", "project:generate"], "command": "template:generate:project", diff --git a/messages/microfrontend.md b/messages/microfrontend.md new file mode 100644 index 00000000..6de05278 --- /dev/null +++ b/messages/microfrontend.md @@ -0,0 +1,51 @@ +# examples + +- Generate an MFE wrapper LWC in the current directory: + + <%= config.bin %> <%= command.id %> --name MyMfeWrapper --src https://app.example.com --sandbox allow-forms --shell-title "Expense Report Widget" + +- Generate an MFE wrapper LWC in the "force-app/main/default/lwc" directory with multiple sandbox tokens: + + <%= config.bin %> <%= command.id %> --name MyMfeWrapper --src https://app.example.com --sandbox allow-forms --sandbox allow-scripts --shell-title "Expense Report Widget" --output-dir force-app/main/default/lwc + +# summary + +Generate a Lightning Web Component that wraps the lightning-mfe-shell base component. + +# description + +Generates a Lightning Web Component bundle that consumes the first-party component, pre-wired with the three required attributes: the widget URL (src), iframe sandbox tokens, and an accessible iframe title (shell-title). + +The generated bundle contains four files (.html, .js, .js-meta.xml, .css) in a directory named with the camelCased component name. The bundle must live under a parent folder named "lwc". + +# flags.name.summary + +PascalCase name of the generated component. + +# flags.name.description + +The component name is also used (camelCased) as the LWC folder name and file stem. Must contain only alphanumeric characters and start with a letter. + +# flags.src.summary + +Absolute https URL the iframe will load. + +# flags.src.description + +The URL is bound to the "src" attribute as a reactive property in the generated LWC. Must use https; plain http is only allowed for localhost or 127.0.0.1 (for local development). + +# flags.sandbox.summary + +Iframe sandbox token (specify the flag multiple times to set more than one token). + +# flags.sandbox.description + +Each token is written into the space-separated "sandbox" attribute on . Only W3C-defined sandbox tokens are accepted. + +# flags.shell-title.summary + +Accessible title for the embedded iframe. + +# flags.shell-title.description + +Written to the "shell-title" attribute on and used as the iframe's accessible name (announced by screen readers). Must be a non-empty string. diff --git a/src/commands/template/generate/microfrontend.ts b/src/commands/template/generate/microfrontend.ts new file mode 100644 index 00000000..0e5746e9 --- /dev/null +++ b/src/commands/template/generate/microfrontend.ts @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2026, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ + +import { Flags, loglevel, orgApiVersionFlagWithDeprecations, SfCommand, Ux } from '@salesforce/sf-plugins-core'; +import { CreateOutput, MicrofrontendOptions, TemplateType } from '@salesforce/templates'; +import { Messages } from '@salesforce/core'; +import { getCustomTemplates, runGenerator } from '../../../utils/templateCommand.js'; +import { internalFlag, outputDirFlagLightning } from '../../../utils/flags.js'; + +Messages.importMessagesDirectoryFromMetaUrl(import.meta.url); +const messages = Messages.loadMessages('@salesforce/plugin-templates', 'microfrontend'); + +// Keep in-sync with VALID_SANDBOX_TOKENS in salesforcedx-templates/src/generators/microfrontendGenerator.ts +const SANDBOX_TOKENS = [ + 'allow-forms', + 'allow-modals', + 'allow-orientation-lock', + 'allow-pointer-lock', + 'allow-popups', + 'allow-popups-to-escape-sandbox', + 'allow-presentation', + 'allow-same-origin', + 'allow-scripts', + 'allow-storage-access-by-user-activation', + 'allow-top-navigation', + 'allow-top-navigation-by-user-activation', +] as const; + +export default class Microfrontend extends SfCommand { + public static readonly summary = messages.getMessage('summary'); + public static readonly description = messages.getMessage('description'); + public static readonly examples = messages.getMessages('examples'); + public static readonly hidden = true; + + public static readonly flags = { + name: Flags.string({ + char: 'n', + summary: messages.getMessage('flags.name.summary'), + description: messages.getMessage('flags.name.description'), + required: true, + }), + src: Flags.string({ + char: 's', + summary: messages.getMessage('flags.src.summary'), + description: messages.getMessage('flags.src.description'), + required: true, + }), + sandbox: Flags.option({ + summary: messages.getMessage('flags.sandbox.summary'), + description: messages.getMessage('flags.sandbox.description'), + options: SANDBOX_TOKENS, + multiple: true, + required: true, + })(), + 'shell-title': Flags.string({ + summary: messages.getMessage('flags.shell-title.summary'), + description: messages.getMessage('flags.shell-title.description'), + }), + 'output-dir': outputDirFlagLightning, + 'api-version': orgApiVersionFlagWithDeprecations, + internal: internalFlag, + loglevel, + }; + + public async run(): Promise { + const { flags } = await this.parse(Microfrontend); + + const flagsAsOptions: MicrofrontendOptions = { + componentname: flags.name, + src: flags.src, + sandbox: flags.sandbox.join(' '), + shellTitle: flags['shell-title'] ?? flags.name, + outputdir: flags['output-dir'], + apiversion: flags['api-version'], + internal: flags.internal, + }; + + return runGenerator({ + templateType: TemplateType.Microfrontend, + opts: flagsAsOptions, + ux: new Ux({ jsonEnabled: this.jsonEnabled() }), + templates: getCustomTemplates(this.configAggregator), + }); + } +}