Skip to content

Commit

Permalink
Add new activate and deploy LWC command for datapacks of type OmniScript
Browse files Browse the repository at this point in the history
  • Loading branch information
Codeneos committed Aug 18, 2023
1 parent aeacbe5 commit 8e25c1c
Show file tree
Hide file tree
Showing 18 changed files with 353 additions and 127 deletions.
13 changes: 9 additions & 4 deletions packages/omniscript/src/omniScriptActivator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export class OmniScriptActivator {
// Deploy LWC when required
if (options?.skipLwcDeployment !== true && script.isLwcEnabled) {
const definition = await this.definitionProvider.getScriptDefinition(script.id);
await this.deployLwcComponent(definition, options);
await this.deployLwc(definition, options);
}

if (options?.reactivateDependentScripts && script.isReusable) {
Expand Down Expand Up @@ -225,20 +225,25 @@ export class OmniScriptActivator {
*/
public async activateLwc(id: string, options?: OmniScriptActivationOptions) {
const definition = await this.definitionProvider.getScriptDefinition(id);
await this.deployLwcComponent(definition, options);
await this.deployLwc(definition, options);
}

/**
* Get the LWC component bundle as metadata package for the specified OmniScript
* @param id Id of the OmniScript
* @returns Deployable Metadata package
*/
public async getLwcComponentBundle(id: string) {
public async getMetadataPackage(id: string) {
const definition = await this.definitionProvider.getScriptDefinition(id);
return this.lwcCompiler.compileToPackage(definition);
}

private async deployLwcComponent(definition: OmniScriptDefinition, options?: OmniScriptActivationOptions) {
/**
* Generate the LWC component bundlen for the specified OmniScript definition and deploy it to the org.
* @param definition Definition of the OmniScript to deploy
* @param options Extra options that control how the script is activated
*/
public async deployLwc(definition: OmniScriptDefinition, options?: OmniScriptActivationOptions) {
const timer = new Timer();
const apiLabel = options?.toolingApi ? 'tooling' : 'metadata';
this.logger.info(`Deploying LWC ${definition.bpType}/${definition.bpSubType} (${apiLabel} api)...`);
Expand Down
4 changes: 3 additions & 1 deletion packages/omniscript/src/omniScriptDefinitionGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ export class OmniScriptDefinitionGenerator implements OmniScriptDefinitionProvid
}

private async createRecordsFromDatapack(datapack: VlocityDatapack) {
const scriptRecord = this.createRecord(datapack.data);
// OmniScripts do not have version when exported; force them to version 1 so we don't get undefined version errors
const scriptData = { ...datapack.data, "%vlocity_namespace%__Version__c": datapack.version ?? 1 };
const scriptRecord = this.createRecord(scriptData);
const elementRecords = datapack.Element__c.map(ele => this.createRecord(ele));
return { scriptRecord, elementRecords };
}
Expand Down
2 changes: 1 addition & 1 deletion packages/vlocity-deploy/src/deploymentSpecs/omniScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ export class OmniScript implements DatapackDeploymentSpec {
await forEachAsyncParallel(Iterable.filter(event.getDeployedRecords('OmniScript__c'), r => this.lwcEnabledDatapacks.has(r.datapackKey)), async record => {
try {
if (event.deployment.options.useMetadataApi) {
packages.push(await this.activator.getLwcComponentBundle(record.recordId));
packages.push(await this.activator.getMetadataPackage(record.recordId));
} else {
await this.activator.activateLwc(record.recordId, { toolingApi: true });
}
Expand Down
39 changes: 26 additions & 13 deletions packages/vscode-extension/commands.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,6 @@ vlocode.createOmniscriptLwc:
group: v_vlocity
menus:
- menu: commandPalette
vlocode.generateLwc:
title: 'Vlocity: Generate LWC'
group: v_vlocity
menus:
- menu: commandPalette
- menu: explorer/context
when: &generateLwcWhen
- resourceScheme == folder && resourcePath =~ /.+\/OmniScript\/.+/
- resourceScheme == folder && resourcePath =~ /.+\\OmniScript\\.+/
- resourceScheme == file && resourcePath =~ /.+\/OmniScript\/.+\/.+_DataPack.json$/
- resourceScheme == file && resourcePath =~ /.+\\OmniScript\\.+\\.+_DataPack.json$/
- menu: editor/context
when: *generateLwcWhen

# hide commands
vlocode.buildDatapack:
Expand Down Expand Up @@ -320,3 +307,29 @@ vlocode.developerLogs.setLogVisibility:
menus:
- menu: view/title
group: navigation

# OmniScript LWC commands
vlocode.omniScript.generateLwc:
title: 'OmniScript: Generate LWC'
group: v_vlocity_omniscript
menus: &omniScriptCommandMenus
- menu: explorer/context
when:
- resourceScheme == folder && resourcePath =~ /.+\\OmniScript\\[^\\]+$/
- resourceScheme == folder && resourcePath =~ /.+\/OmniScript\/[^\/]+$/
- resourceScheme == file && resourcePath =~ /.+\/OmniScript\/.+\/.+\.json$/
- resourceScheme == file && resourcePath =~ /.+\\OmniScript\\.+\\.+\.json$/
- menu: commandPalette
when: &whenOmniScript
- resourceScheme == file && resourcePath =~ /.+\/OmniScript\/.+\/.+\.json$/
- resourceScheme == file && resourcePath =~ /.+\\OmniScript\\.+\\.+\.json$/
- menu: editor/context
when: *whenOmniScript
vlocode.omniScript.deployLwc:
title: 'OmniScript: Deploy as LWC'
group: v_vlocity_omniscript
menus: *omniScriptCommandMenus
vlocode.omniScript.activate:
title: 'OmniScript: (Re-)Activate'
group: v_vlocity_omniscript
menus: *omniScriptCommandMenus
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export abstract class DatapackCommand extends CommandBase {
*/
protected async getSalesforceRecords(datapacks: VlocityDatapack[], options?: { showRecordSelection?: boolean }) {
const matchingRecords = await mapAsync(await this.datapackService.getDatapackRecords(datapacks), async (matchedRecords, i) =>
options?.showRecordSelection
options?.showRecordSelection && matchedRecords.length > 1
? this.showRecordSelection(matchedRecords, datapacks[i].datapackType)
: this.getBestRecord(matchedRecords, datapacks[i].datapackType)
);
Expand All @@ -72,7 +72,7 @@ export abstract class DatapackCommand extends CommandBase {
sobjectType: datapack.sobjectType,
datapackType: datapack.datapackType,
id: matchingRecords[i]?.Id,
record: matchingRecords[i]
values: matchingRecords[i]
}));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { VlocityToolsDeployment } from '../../lib/vlocity/vlocityToolsDeploy';
const deployModeSuggestionKey: string = 'deploymodeSuggestion-0.17.0';
const suggestionInterval: number = 9 * 24 * 3600 * 1000;

@vscodeCommand(VlocodeCommand.deployDatapack, { focusLog: true })
@vscodeCommand(VlocodeCommand.deployDatapack, { focusLog: true, showProductionWarning: true })
export class DeployDatapackCommand extends DatapackCommand {

/**
Expand Down Expand Up @@ -51,13 +51,6 @@ export class DeployDatapackCommand extends DatapackCommand {
return;
}

// Prevent prod deployment if not intended
if (await this.vlocode.salesforceService.isProductionOrg()) {
if (!await this.showProductionWarning(false)) {
return;
}
}

// Suggest vlocode?
if (datapackHeaders.length > 1) {
await this.suggestDeploymentModeChange();
Expand Down
54 changes: 0 additions & 54 deletions packages/vscode-extension/src/commands/datapacks/generateLwc.ts

This file was deleted.

4 changes: 3 additions & 1 deletion packages/vscode-extension/src/commands/datapacks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ export * from './exportDatapackCommand';
export * from './openSalesforceCommand';
export * from './refreshDatapackCommand';
export * from './renameDatapackCommand';
export * from './generateLwc';
export * from './omniScriptGenerateLwc';
export * from './omniScriptDeployLwc';
export * from './omniScriptActivate';
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import * as vscode from 'vscode';

import { OmniScriptActivationOptions, OmniScriptActivator, OmniScriptDefinitionGenerator, OmniScriptSpecification, VlocityDatapack } from '@vlocode/vlocity-deploy';
import { VlocodeCommand } from '../../constants';
import { vscodeCommand } from '../../lib/commandRouter';
import { DatapackCommand } from './datapackCommand';
import { container } from '@vlocode/core';
import { ActivityProgress } from '../../lib/vlocodeActivity';

@vscodeCommand(VlocodeCommand.omniScriptActivate, { focusLog: true, showProductionWarning: true })
export default class ActivateOmniScriptCommand extends DatapackCommand {

public execute(...args: any[]) : Promise<void> {
return this.executeWithSelection(args[1] || [args[0] || this.currentOpenDocument]);
}

protected async executeWithSelection(selectedFiles: vscode.Uri[]) : Promise<void> {
const datapacks = await this.loadDatapacks(selectedFiles);
const options = {
toolingApi: true,
remoteActivation: false,
reactivateDependentScripts: false
};

if (datapacks.length === 0) {
throw new Error('Selected file is not a Vlocity OmniScript DataPack');
}

const hasReusableScripts = datapacks.some(datapack => datapack.IsReusable__c);
if (hasReusableScripts && await this.promptDependencyReactivation()) {
options.reactivateDependentScripts = true;
}

return this.vlocode.withActivity('OmniScript', (progress) => this.activateScripts(datapacks, options, progress));
}

protected async activateScripts(
datapacks: VlocityDatapack[],
options: OmniScriptActivationOptions,
progress: ActivityProgress
) : Promise<void> {
const activated = new Array<OmniScriptSpecification>();
const failed = new Array<OmniScriptSpecification & { error: unknown }>();

for (const datapack of datapacks) {
const omniScriptSpec = {
type: datapack.Type__c,
subType: datapack.SubType__c,
language: datapack.Language__c
};

if (!omniScriptSpec.subType || !omniScriptSpec.type) {
throw new Error(`Datapack is not of type OmniScript: ${datapack.headerFile}`);
}

progress.report({ message: `Activating ${omniScriptSpec.type}/${omniScriptSpec.subType}...` });

try {
await container.get(OmniScriptActivator).activate(omniScriptSpec, options);
activated.push(omniScriptSpec);
} catch (error) {
failed.push({...omniScriptSpec, error });
this.logger.error(`Failed to activate ${omniScriptSpec.type}/${omniScriptSpec.subType}: ${error.message}`);
}
}

void vscode.window.showInformationMessage(`Activated ${activated.length} OmniScript(s)`);
}

private async promptDependencyReactivation() : Promise<boolean> {
const outcome = await vscode.window.showQuickPick([
{ value: true, label: 'Yes', description: 'Reactivate scripts that use this script as dependency' },
{ value: false, label: 'No', description: 'Only reactivate this script and do not refresh any scripts embedding this script as dependency' }
], {
placeHolder: 'Reactivate dependent scripts?'
});
if (!outcome) {
throw new Error('User cancelled operation');
}
return outcome.value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import * as vscode from 'vscode';

import { OmniScriptActivator, OmniScriptDefinitionGenerator, VlocityDatapack } from '@vlocode/vlocity-deploy';
import { VlocodeCommand } from '../../constants';
import { vscodeCommand } from '../../lib/commandRouter';
import { DatapackCommand } from './datapackCommand';
import { container } from '@vlocode/core';
import { ActivityProgress } from '../../lib/vlocodeActivity';

@vscodeCommand(VlocodeCommand.omniScriptDeployLwc, { focusLog: true, showProductionWarning: true })
export default class DeployLwcCommand extends DatapackCommand {

public execute(...args: any[]) : Promise<void> {
return this.executeWithSelection(args[1] || [args[0] || this.currentOpenDocument]);
}

protected async executeWithSelection(selectedFiles: vscode.Uri[]) : Promise<void> {
const datapacks = await this.loadDatapacks(selectedFiles)

if (datapacks.length === 0) {
throw new Error('Selected file is not a Vlocity OmniScript DataPack');
}

const notLwcEnabled = datapacks.some(datapack => !datapack.IsLwcEnabled__c);
if (notLwcEnabled) {
const notLwcWarningResult = await vscode.window.showWarningMessage(
'Not all selected OmniScripts are LWC enabled. Only LWC enabled OmniScripts can be deployed as LWC components. ' +
'Deploying non-LWC enabled OmniScripts can result in errors during deployment.',
'Continue', 'Cancel'
);
if (notLwcWarningResult !== 'Continue') {
return;
}
}

return this.vlocode.withActivity('OmniScript', (progress) => this.deployLwc(datapacks, progress));
}

protected async deployLwc(datapacks: VlocityDatapack[], progress: ActivityProgress) : Promise<void> {
for (const datapack of datapacks) {
progress.report({ message: `Generating ${datapack.name} definitions...`, total: datapacks.length, increment: 1 });
const definition = await container.get(OmniScriptDefinitionGenerator).getScriptDefinitionFromDatapack(datapack);

progress.report({ message: `Deploying ${datapack.name} LWC...` });
await container.get(OmniScriptActivator).deployLwc(definition, {
toolingApi: true,
remoteActivation: false,
reactivateDependentScripts: true
});
}
void vscode.window.showInformationMessage(`Deployed LWC components for ${datapacks.length} OmniScript(s)`);
}
}
Loading

0 comments on commit 8e25c1c

Please sign in to comment.